Wednesday, December 24, 2008

The Helicopter story

I just read a nice article (check this link), it spoke about the principle of orthogonality in software design. Without further ado, here's the helicopter story.

A helicopter has four main controls: foot pedals, collective pitch lever, cyclic, and throttle. The foot pedals control the tail rotor. With the foot pedals you can counteract the torque of the main blade and, basically, point the nose where you want the helicopter to go. The collective pitch lever, which you hold in your left hand, controls the pitch on the rotor blades. This lets you control the amount of lift the blades generate. The cyclic, which you hold in your right hand, can tip one section of the blade. Move the cyclic, and the helicopter moves in the corresponding direction. The throttle sits at the end of the pitch lever.

It sounds fairly simple. You can use the pedals to point the helicopter where you want it to go. You can use the collective to move up and down. Unfortunately, though, because of the aerodynamics and gyroscopic effects of the blades, all these controls are related. So one small change, such as lowering the collective, causes the helicopter to dip and turn to one side. You have to counteract every change you make with corresponding opposing forces on the other controls. However, by doing that, you introduce more changes to the original control. So you're constantly dancing on all the controls to keep the helicopter stable.

That's kind of similar to code. We've all worked on systems where you make one small change over here, and another problem pops out over there. So you go over there and fix it, but two more problems pop out somewhere else. You constantly push them back—like that Whack-a-Mole game—and you just never finish. If the system is not orthogonal, if the pieces interact with each other more than necessary, then you'll always get that kind of distributed bug fixing.

The funny thing about the helicopter story is that I'm not a helicopter pilot. When I wrote the helicopter story, I wanted to make sure it was accurate. I knew of a USENET group on helicopters, so I posted the helicopter story saying, "This is what I'm intending to write about how helicopter controls work. Is it correct? A helicopter pilot emailed me and said, "I read what you wrote about controlling helicopters. I didn't sleep all night."

Wednesday, December 17, 2008

Add index to your table to speed up queries

I'm not a database expert here and I just learned this tip today.

If you have a large table and one or more columns are often used in the where clause, you might want to consider setting up index for those columns.
But one thing to note, in oracle (maybe for other database also), if you're doing a calculation on the column in the where clause, your index isn't used by the optimizer.
e.g. where column * 12 > 1000

My friend today was trying to optimize a query, by introducing an index, the result was awesome, instead of doing a full table scan (the size around 60 something mb), the optimizer use the index thereby reducing the cost and the time consumed.

One other option that was set is to allow the database engine to execute parallel queries on the table.

But if we setup too many indices, will that make inserting record to the table much slower?

Tuesday, December 16, 2008

Beans that you could access from your dashlet in alfresco

If you're developing a custom dashlet or any jsf page for any purpose in alfresco, you could use the beans listed in (alfresco\WEB-INF\faces-config-beans.xml).

Here's the list :
  • MultilingualManageDialog (The bean for the Delete Category screen)
  • ManagePermissionsDialog (The bean for the Manage Permissions)
  • MakeMultilingualDialog (The bean that make a document multilingual)
  • EditMLContainerDialog (The bean that edit the multilinguals properties of a document)
  • AddTranslationWithoutContentDialog (The bean that add a new translation without content)
  • AddTranslationDialog (The bean that add a translation with a content)
  • LoginBean (The bean that backs up the Login screen)
  • NavigationBean (The bean that holds navigation state)
  • BrowseBean (The bean that holds folder browse state)
  • AboutBean (Bean that provides information for the About page)
  • DialogManager (Bean that manages the dialog framework)
  • WizardManager (Bean that manages the wizard framework)
  • CreateSpaceDialog (The bean that backs up the Create Space Dialog)
  • CreateSpaceWizard (The bean that backs up the Create Space Wizard)
  • DeleteSpaceDialog (The bean that backs up the Delete Space Dialog)
  • ClipboardBean (The bean that manages a users Clipboard state)
  • RecentSpacesBean (The bean that manages the state for the Recent Spaces Shelf component)
  • UserShortcutsBean (The bean that manages the state for the User Shortcuts Shelf component)
  • SearchProperties (The bean that holds a state for the Advanced Search screen)
  • AdvancedSearchDialog (The bean that holds a state for the Advanced Search screen)
  • UsersBeanProperties (The bean that holds state for the Users screen)
  • UsersDialog (The bean that holds state for the User Management screens)
  • GroupsDialog (The bean that holds state for the Groups Management screens)
  • CategoriesProperties (The bean that holds state for the Category Management screens)
  • CategoriesDialog (The bean that holds state for the Category Management screens)
  • EditSpaceDialog (The bean that backs up the Edit Space Dialog)
  • AddContentDialog (The bean that backs up the Add Content Dialog)
  • CreateContentWizard (The bean that backs up the Create Content Wizard)
  • EditContentWizard (The bean that backs up the Edit Content Wizard)
  • ViewContentPropertiesDialog (The bean that backs up the View Content Properties Dialog)
  • SetContentPropertiesDialog (The bean that backs up the Set Content Properties Dialog)
  • ..........
  • WorkflowBean
  • and a lot more....

I can't believe that the list is so long that it even make me think to create a small program to load the xml file and parse it just to get this list :)
Anyway, bottom line is these beans might help you, knowing that they're exist already a help.

Monday, December 15, 2008

Alfresco tips

The tips that I will write here might seem silly but it works for me and I do hope it will help someone else and... I think I'll continue to add more items on this list someday.

Should we start now? :)

  1. Always read the wiki thoroughly, sometimes one page won't help you, other pages might contain the information you might need (sometimes I feel they're scattered and I just have to gather them pieces by pieces).
  2. Read the existing code/example, it will certainly help you. For example, if you're creating a dashlet, look at the other dashlets already available.
  3. In case you need to go deep (read : debugging alfresco), you could try to download the code, build it and run it :)
  4. In case the above is too difficult, you could try to at least get the source and put it in a project in eclipse (or any IDE) and remotely debug alfresco (see my post) .
  5. If you need to debug the workflow, get jBPM source code and do the same thing as no 4.
  6. Do yourself a favour by writing down all the changes you've done in alfresco in case you need to revisit it later, I can assure you that you won't be able to remember it for long (unless you're playing with alfresco everyday :).
  7. If you're creating a custom workflow and at some point in your workflow you need to make a branch based on some properties value, use a decision node.
  8. If you're creating a custom workflow, you might need to consider reading jbpm's documentation, especially on the jpdl chapter
  9. Use jpdl designer (free!!) to build your workflow, it will do you a favour later when you come back to your workflow. Go to http://www.eclipse.org or download jBPM GPD.

This is it for the moment, more to come later.

Monday, November 24, 2008

Alfresco workflow package actions

I'm writing this post to serve as a reminder for later need because it's a bit difficult to look for it in Alfresco documentation "jungle" :) (no offense, I'm still grateful that I could access Alfresco's documentation).

Each workflow instance in Alfresco works against a document, the start task "submit" the document, the other tasks in the workflow might add another document, edit attached document, remove attached document and only allowed to read the attached document. This behaviour is set in the workflow model by overriding bpm:packageActionGroup and bpm:packageActionItemGroup.

List of action groups available by default :
  • read_package_item_actions
    allow viewing of package items
  • edit_package_item_actions
    above + allow modification (edit, checkout, ...) of package items
  • edit_and_remove_package_item_actions
    above + allow removal of package items
  • remove_package_item_actions
    allow removal (but not modification) of package items
  • add_package_item_actions
    allow addition of new package items
Custom action also supported but up to now I still have to find out how.

Sample model definition which overrides the default action.
<type name="mynamespace:taskname">
<parent>bpm:workflowTask</parent>
<overrides>
<property name="bpm:packageActionGroup">
<default>add_package_item_actions</default>
</property>
<property name="bpm:packageItemActionGroup">
<default>edit_package_item_actions</default>
</property>
</overrides>
</type>


I guess this is enough for now.

Passing values to your freemarker template in alfresco

This story started when my teammate needed the value of JSESSIONID from alfresco and bla bla bla... So, in short, this is how I managed to pass the session id.

  1. Create a simple model (javabean class) to pass the value to the template, in the class create a method to return a Map containing the values needed, the keys used to store the values are the keys that will be accessed in the template.

  2. public Map getTemplateModel() {
    Map result = new HashMap();

    result.put("sessionId", getSessionId());

    return result;
    }

  3. Register the class as a managed bean in WEB-INF/faces-config-custom.xml (pasting the content here is a bit difficult, until I know how to easily paste an xml content to the post I might not post it). Actually it's not that difficult to register a managed bean, just look at the sample in faces-config-beans.xml.
  4. <managed-bean>
    <description>
    Helper bean providing access to http servlet request's related properties
    and many other things.
    </description>
    <managed-bean-name>SanzModel</managed-bean-name>
    <managed-bean-class>com.sanz.model.TemplateModel</managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
    </managed-bean>
  5. Use the bean name as the model passed to the template.
  6. <r:template template="/alfresco/templates/elnusa/elnusa.html.ftl" model="#{Elnusa.templateModel}"/>
  7. Access the value in the template, just like the way default values provided by alfresco are accessed.

That's all, I guess I have to sleep now, already late...


Reference :
  1. Template Guide

Sunday, November 16, 2008

How to create a custom dashlet in Alfresco

On this post, I'll try to put in a simple example on creating a hello dashlet.
I'm using a standalone Alfresco (apache tomcat included).

Step by step on creating dashlet in Alfresco :
  1. Create a freemarker template for the dashlet and name it filename.html.ftl (e.g. hello.html.ftl). For freemarker syntax please see http://freemarker.org/. Sample content :
  2. <#assign name = person.properties.userName>
    Hello ${name}
  3. Save the file in tomcat\webapps\alfresco\WEB-INF\classes\alfresco\templates\, you could also a directory inside and put your file in your directory.
  4. Create a jsp file that will include the template file created on step 1. The content of the jsp file would be :
  5. <%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %>

    <%-- Note that this template is loaded from the classpath --%>
    <r:template template="/alfresco/templates/hello.html.ftl">
    </r:template>

  6. Save the jsp file in tomcat\webapps\alfresco\jsp\dashboards\dashlets.
  7. Open web-client-config.xml, you can find it in tomcat\webapps\alfresco\WEB-INF\classes\alfresco.
  8. Register the new dashlet, find "dashlets" (without quotes) in web-client-config.xml, add the following configuration :
  9. <dashlet id="hello" label="Hello Dashlet"
    description="My Hello Dashlet"
    jsp="/jsp/dashboards/dashlets/hello.jsp">
    </dashlet>
  10. To see the new dashlet in action, just restart alfresco, login, configure the dashboard and pick the new dashlet.

That's all the steps for creating a simple dashlet, the key lies on the free marker template (besides the configuration), you could put almost anything over there to render anything you want (of course as long as it's possible :)

Wednesday, October 29, 2008

Apache ......> 2 mins ...... JBoss = Timeout

The thing is when the report is prepared it might took around 2-3 minutes, and the user after 2 minutes saw a blank page on their browser, no explanation, no clue, nothing.

We have Apache web server works as a proxy to JBoss and we use mod_proxy here (why not proxy_ajp/mod_jk? because we want to simulate our client's config --> they won't allow us to add additional module to their server).

Looking at the log, found the exception :
ClientAbortException: java.net.SocketException: Broken pipe
....

The first idea came to my mind is it must be the browser that send the timeout signal to the server, opening about:config on the browser (Do you know the browser I'm using?) only to find that the timeout configuration is 300 (5 mins). It seems that it's not the browser to blame on the timeout.

The second idea, it's broken pipe... is it possible that apache buffer is not large enough? Then other idea come up, is it possible that Apache is the one to "blame" for causing the timeout?
Yep, indeed, the default timeout configuration (/etc/httpd/httpd.conf) is 120secs.

#
# Timeout: The number of seconds before receives and sends time out.
#
Timeout 120

Changing it to 300 (5 mins) should be enough to allow the report to be prepared fully.

One problem solved, one lesson learned and one happy customer we got.

Thursday, October 23, 2008

Setting JBoss IP address

Starting jboss without configuring the ip address will set the default address for jboss to localhost which is fit for development or maybe for a production server, where apache is used as the proxy to jboss and resides in the same machine.

To set the ip address for JBoss :
  • To a specific IP address
  • run.sh -b 10.62.31.31
  • To localhost or the IP address assigned to the server
  • run.sh -b 0.0.0.0
There's all to set the ip address, somehow I still wonder why JBoss prefer this way to configure the ip address :)

Saturday, October 11, 2008

Debugging application server as remote application

The need was to debug Resin 3.1.0 in eclipse, however there's no plugin for Resin 3.1.0 in eclipse (at least until now) to my own amazement.
Fortunately, there's still a workaround which is to debug the application server as if it is a remote java application.

To do that, we need to add the parameter below before starting the server

-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=12345

(-Xnoagent already deprecated, we could remove it anyway, so why do I put it there? Just to let you know that it exists and if you still use JDK1.1 then use it otherwise loose it)

Adding the parameter above means that we could attach a debugger to localhost:12345 (assuming I'm debugging application server running at my computer), the address could be adjusted to a different port as long as the port is unused.

Then on the IDE of your choice (I've tried eclipse and netbeans), just open a remote debug session and put localhost as the host and 12345 as the port. If your IDE successfully attaching a debugger to the server, then all you need to do is set breakpoint(s) to your application code which was deployed to the server. Access the application and the server will be suspended when it arrives at the breakpoint set before.

That's all for now, any question just shoot.

Note : I'm not explaining all those parameters in detail, if you're interested, please visit this link.

Wednesday, October 08, 2008

Calling webscript with no Basic authentication

My case was that I need to invoke web script without triggering the HTTP basic authenticator, 1 week of reading the wiki and googling, I almost accept that web script requires HTTP basic authentication.
But thanks to the answer on my alfresco post, there are 3 ways of authentication for web script.

  1. /alfresco/service or /alfresco/s (mapped to HTTP Basic Authenticator)
  2. /alfresco/wcservice or /alfresco/wcs (mapped to Web Client Authenticator)
  3. /alfresco/168service or /alfresco/168s (mapped to JSR-68 Authenticator)

I could use /alfresco/wcs to invoke my web script from my dashlet without popping up the authentication dialog box and it opens up the possibilities for me integrating other applications :)

Sunday, October 05, 2008

Custom dashlets (alfresco again)

I couldn't believe it, is it me or is it alfresco documentation that sometimes seems to be unfriendly. Here's the case, I was thinking of having my own dashlet, I went to http://wiki.alfresco.com/wiki/User_Configurable_Dashboards#Writing_Dashboard_Components, done creating the jsp page, I didn't know how to make my dashlet appears on the "magic list" of dashlet components.

I then read from a source which told me to add my dashlet to the web-client-config.xml, tried that and it was successfull. But I was still curious where did I do wrong during reading the manual that I didn't even notice that configuration file, it turns out that the section that explain about the configuration file is "Configuring Available Components", and down below on the section "Writing Dashboard Components" doesn't put any clue that I have to add/register the new dashlet over there (at that time I just skimmed through the configuring part since it says "available" component).

I guess I have to read alfresco's documentation thoroughly and carefully, but I'm not being ungrateful here, I'm really do grateful for Alfresco, but please if a nice and friendly sample could be written, please write it for people like me.

Just a reminder for me on how to create a dashlet :
  1. Prepare a template (free marker) and put it in WEB-INF/classes/alfresco/template (I believe this step is optional)
  2. Prepare the jsp page that refer to the template (if you create one) and put the jsp file in jsp/dashboards/dashlets (should it always be this directory? got to find out, not now though.. I wanna sleep)
  3. Add/register the newly created dashlet to web-client-config.xml in WEB-INF/classes/alfresco

Once again, I'm grateful for Alfresco but I'll be more grateful if there could be a friendlier documentation (or could I help?)

Saturday, October 04, 2008

Starting an alfresco workflow using Javascript API

The script to execute workflow is as below :

var workflow = actions.create("start-workflow");
workflow.parameters.workflowName = "jbpm$sanz:testWorkflow";
workflow.parameters["bpm:workflowDescription"] = upload.name;
workflow.parameters["bpm:groupAssignee"] = people.getGroup("GROUP_IT Manager");
workflow.parameters["sanz:notifyMe"] = true;
var futureDate = new Date();
futureDate.setDate(futureDate.getDate() + 7);
workflow.parameters["bpm:workflowDueDate"] = futureDate;
workflow.execute(document);


A bit explanation :
  • "start-workflow" is the action name to create a workflow action (see Action API)
  • workflow name is prefixed by "jbpm$", the workflow name used is the name set in the process definition along with its namespace
  • other parameters as defined in the task(inside the start-state) 's type could be set here, e.g. the "sanz:notifyMe" property in the example above
  • pass a document (Content noderef) to workflow.execute. Remember if we start a workflow from the web-client interface, we always start from a content/document

Tips :
  • if you want to pass a group as the groupAssignee, we can use people.getGroup(groupName) API, but one thing to note, the group name to pass is : GROUP_group name. You should add "GROUP_" prefix to your group name.
  • to pass assignee, use people.getPerson(assignee name)
  • to pass assigness, wrap the assigness as array, using [], e.g. [people.getPerson("me"), people.getPerson("you")]

I guess that's all for now. Next target, synchronize user/group to ldap (or from ldap?)

Custom workflow in alfresco

Alfresco, at first glance it looks like just another document management system.. wait, I'm not here to talk about alfresco as a DMS, let's get back to the main topic.

How to create a custom advance workflow in Alfresco

Before continuing, the main reason I'm writing this is to make life a lot simpler for developers who are told to create an advance workflow (I hope), where I'm having a hard time myself creating one.

One thing to note, I'm not repeating what is already in the manual, so better to read the manual first.
  1. Read http://wiki.alfresco.com/wiki/WorkflowAdministration first.
  2. Create the process definition, things to note :
    • Declare the swimlane for each actor/group of actors, one special swimlane called Initiator (which represent the initiator of the workflow)
    • Another special state is start-state, this is the point where we collect required parameters for the workflow to start, e.g. the reviewer, due date, etc (just remember this at this moment).
    • Declare task for each task-node
    • For each task declared, specify the swimlane (if we don't, who will handle the task?)
    • For each task declared, specify a name for the task. The task name relates to the type of model that we will use, either create a new one or use an existing, e.g. wf:submitAdhocTask
    • Deploy the new process definition, it's easier to deploy the process through JBoss jBPM Process Designer
    • Alternatively instead of using the process designer, you could put your definition file in [Alfresco installation]\tomcat\webapps\alfresco\WEB-INF\classes\alfresco\extension, create a "workflowDeployer" spring configuration and add the spring configuration to classes/alfresco/application-context.xml
  3. Create a new model or use an existing one. To create a new model :
    • You can safely follow what's in the manual (step 2 : Create the task model)
    • Declare your own namespace (for those who aren't familiar with xml terms, namespace is like a package in Java, you could specify your own URI)
    • Import bpm's type, by adding the import statement specifying the bpm uri.
    • Create type for each task in the process definition, to be exact, the name of the type is the same name as the task's name. Don't create the type if you use an existing one in your task
    • Each type should has a parent, remember that we're creating types for process not for other purpose, the parent should be a bpm type. For type for task in start-state, the parent is bpm:startTask, for the other, we could use bpm:workflowTask
    • To view/modify content on the workflow on a specific task, we have a workflow package operation ready for use, see the manual on http://wiki.alfresco.com/wiki/WorkflowAdministration#Workflow_Package_Actions
    • Since the new type extends bpm's type, some properties are already in place, to introduce new one just declare the properties inside the type, see the manual on http://wiki.alfresco.com/wiki/WorkflowAdministration#Step_2:_Create_the_Task_Model
    • Deploy the model
      • Put your model in [Alfresco installation]\tomcat\webapps\alfresco\WEB-INF\classes\alfresco\extension
      • Create a new spring configuration file to load the model. The file name should end with context.xml (e.g. my-file-context.xml), put it in extension directory, alfresco will pick it up when it starts, see the manual for sample spring beans definition on http://wiki.alfresco.com/wiki/WorkflowAdministration#Deploying_the_Task_Model
      • Restart the server

  4. Create web client configuration, the purpose is alfresco doesn't know how to render the "type" that we just created, it needs the so called web-client configurator. I have nothing to say about this, so just read on the available manual One thing to note, update web-client-application-context.xml to load the custom web-client-xxx-config.xml
  5. Prepare resource bundle for the workflow, my advice is to look at workflow-messages.properties located at ...\classes\alfresco\workflow. Look at the pattern and follow it for your process and types.
  6. Behavior can be added and I'm not going to discuss about it here. One note, it's a bit difficult for me to find a documentation on Alfresco Javascript API, if you're trying to find out what are the properties that a certain root object has, use Alfresco's javascript console and browse through the root object's properties
  7. Use workflow console!!! the url is /alfresco/faces/jsp/admin/workflow-console.jsp. It can undeploy definitions, just what you need when you're in a development stage and still a lot of features that you will surely need

In summary, list of files created :
  1. JPDL (process definition file)
  2. if we do manual deployment, we need custom spring context to deploy the jpdl (along with the model also if needed)
  3. model
  4. custom spring context file (to load the model)
  5. web client config file to tell alfresco how to render our model
  6. Message properties
That's all for now and I might add some other things later. Indeed, it's exciting to use Alfresco, still a lot to learn.

Another source that might help : http://ecmarchitect.com/archives/2007/06/09/756

Wednesday, October 01, 2008

java.awt.headless

We were using JFreeChart at that time, on our development machine everything ran smooth, chart appeared, no error. Until we deployed it on the production server (wait, am I not mentioning any staging server here? yep, no staging server mentioned.. just another recipe for disaster), the chart was gone, error message was the only clue we had. Google here, google there and we ended up with this great remedy that saved our asses.

The error message was :
Can't connect to X11 window server using ':0.0' as the value of the
DISPLAY variable.
java.lang.InternalError: Can't connect to X11 window server
using ':0.0' as the value of the DISPLAY variable.

I've tried to set the DISPLAY variable in the environment to no avail, the other solution we found was to set java.awt.headless=true, indeed this was the option that we need to add before we run the server.
The key was on the production server there was no X-server running (we used rhel), everything done thru the console (which bring to my mind, what is wrong with having a nice GUI helping you, instead of all in text... i'm not against it, I'm just looking for improvement).
Setting headless to true, tells the jvm that it lacks either display device, keyboard or mouse. Luckily for us JFreeChart doesn't use any graphical components that requires a display device.

One more thing to consider if someone is going to build a component related to displaying things on screen.

Thursday, August 21, 2008

Write once run everywhere, eh??

Writing a desktop application in Java means dreaming of an application that we wish will run on any platform. One "fatal" mistake that I saw today, i.e. assuming that the file separator is "\", guess on which platform the application was developed.

To avoid this kind of mistake, simply use File.pathSeparator instead of hardcoding "\" in the code.

Thread, if we playing around with thread, make sure that your threads won't cause any deadlock, if it run in windows, don't you ever believe 100% that it will run in *nix. Each os has different way of scheduling threads, so beware.

Drawing on canvas, handling mouse events, creating custom component, if your code does this, test it on all platforms before you claim that it runs everywhere (at least windows, linux, mac).


It seems the dream of having an application which runs anywhere is not yet fully realized. But still I'm grateful for what Java provides now and will look for the realization of the dream.

Thursday, August 07, 2008

Quantity Always Trumps Quality

I hate to say it but I got to admit that this article has a good argument. I always think that quality is more important than quantity, for example in coding. But I have to admit, only by experience that your quality will be improved.

Mind that. No practice, no improvement on quality :)

Tuesday, August 05, 2008

I don't believe in a framework unless I got the source

As the title said, I don't believe in a framework unless I got the source. The sole reason is the source code is my pass out of trouble (though sometimes it doesn't).

Consider this, you're picking out a framework and after some research you decide to use it in your project. Everybody happy until some weird things happen, you've follow all the procedures still you got this weird things hampering you.

No code = no explanation = hoping that somebody out there also experience this and have their way out so that you could follow them and hopefully your problem will be solved too... finger crossed.

I hope now you know what I mean with having the source code is my pass out of this kind of weird behavior.



Note : I just involved in .NET development, strange errors occurred and it's difficult to reproduce (it is there, 100%!!!). Staring at the code, don't know what is really going on, all that I could do is googling and trying to find a workaround.

Tuesday, March 18, 2008

You should not be alone

When you think that you're alone, you should not be alone.
Especially if you're in a position where you should decide what to do, which way to go, how do things should be done, how do we organize things, how to we adhere to standards, etc.

Remember, you have your team supporting you, talk with them (not to them) and heaven knows, they will give you input that you never think of before.
It just a matter of gathering scattered information and from there on make the decision and learn from it.

Monday, March 10, 2008

Many to many relationship in JPA

I'm using JPA here and I got two objects A and B, the relationship is many to many and B is the owner.
I want to delete object A but still preserving B, the problem is I got a constraint exception since there's a record in the link table which keep a reference to the record that I intended to delete in A.

The solution is to create a native query to remove the row in the link table, then I can remove A.
Hibernate (as my friend said) doesn't have this limitation, so far I don't find the same solution in JPA.

Regarding HQL, there're times where I must revert back to native query to get things done correctly and I wonder is it me that doesn't really know HQL or is it HQL's limitation? sample case I hope will follow later.

Saturday, March 01, 2008

Firebug

Firebug,

It's amazing, I just can't stop recommending firebug to all my colleagues. It's almost like all in one package solution, so far I almost ditch WebDeveloper plugin away (almost here... :) but I'm keeping it in case I might need it.

From modifying css "live", debugging javascript until modifying html element "live", all these you can do in firebug.

I'm not Firebug evangelist, I'm just being a satisfied customer here :) very very satisfied one.

Thursday, February 28, 2008

Load balancing

I surprised myself when I read my old post (wrote it on 28 Feb 2008). What was I thinking? never met someone who use load balancer?? I must had a very small view of the IT world ;)

"A nice article on load balancing with apache, somehow until now I never met someone who use load balancer (even on a big project) and this makes me think... do we really need a load balancer? What are the cases where load balancer is really required?
It seems that upgrading the server is the preferred choice, personally I'm waiting for a chance where I can setup a load balancer :) One more thing that I'm looking forward to see is transparent failover, hopefully I'll see one sooner rather than later."

Now, I stand corrected, load balancer is a must and how do we have a scalable architecture without one?
For my own needs, one of the cheapest solution I believe is to use Apache httpd as a load balancer for my application servers. Here's how to set it up:

1. Edit apache's httpd.conf and below is a sample configuration


 2. Load the modules below by uncommenting them in the LoadModule section in httpd.conf:
- mod_proxy.so
- mod_proxy_balancer.so
- mod_proxy_ajp.so 
- mod_proxy_http.so
- mod_lbmethod_bytraffic.so
- mod_slotmem_shm.so
3. Make sure ajp connector is enabled in Tomcat's server.xml configuration file.
4. Restart apache httpd

I think that's all we need.


Reference:
- http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html
- http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxyset

Tuesday, February 26, 2008

JSF strange behaviors

Two strange behavior of JSF (at least this is what I remembered)
1. Your backing bean only specify getter method (in my case, it returns a collection) and you're using it in h:dataTable. Submitting the form (invoking any action on the page) does nothing, no exception, no sign of anything happening... not a single clue. After one hour wasted, I found out that creating a setter method solves it. It seems that JSF try to call the setter and then fails ungracefully.

2. I have a selectOneMenu and I use a getter method for the selectItems, the List of SelectItem are created whenever the getter is invoked (I know it's not good, just hear the story :). Accessing the page yields exception complaining that there is no selectItem provided (null). Strange thing is the getter method is invoked not in render phase, why? Long story short, I add a property in the backing bean holding the List of selectItem and the getter method is still the same getter method as previously, only at this time I initialize the collection once (better pattern, rite? ;). It works! No more error.


These two strange behaviors that I remembered, are they somehow in the JSF specification?
... I guess I have to try to find out myself.