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.