Posted by: planetjbpm | 5 July, 2009

JPDL xml extensibility

As many of you might know, jBPM is extensible in many ways. You can

  • in the most low level form use the pvm to develop your own processlanguage.
  • extend nodes by overriding the implementations and adapt hibernate mappings
  • create custom taskcontrollers
  • Implement node behviour by putting a class reference on the ‘node’ element
  • implement delegation classes like actionhandlers and assignmenthandlers

What many of you probably do not know is that the processdefinition.xm file besides being parsed is just stored in the database as well and it is very easy to retrieve

ProcessDefinition processDefinition = jBPMContext.getProcessInstance(pid).getProcessDefinition();
FileDefinition fileDefinition = processDefinition.getFileDefinition();
InputStream inputStream = fileDefinition.getInputStream("processdefinition.xml");

Converting this to xml would be the next step so you can have real access to it (XmlUtil being a jbpm class)

Document document = XmlUtil.parseXmlInputStream(inputStream);
Element documentElement = document.getDocumentElement();

Now what could you do with this? Well with access to each element via DOM or XPath, a lot. First of all, the jBPM3 console uses this same concept to read the forms.xml file that contains the mapping from tasknames to form files and reads the xhtml form files from the database this way. It would e.g. not be difficult to change this to use a form attribute on a task element instead of using the forms.xml file

<start-state name="Create new web sale order" >
<task swimlane="buyer" form="form.create.xhtml"/>
<transition to="Evaluate web order" />
</start-state>

This is comparable to what jBPM4 will use. You would not gain much doing this in jBPM 3 since you’d have to do this manually in the gpd.
What else? Well, some of you might remember that jBPM 3.0 it was I believe had the option to automagically generate the forms based on the variables that were present in the task.


<start-state name="Create new web sale order">
<task swimlane="buyer">
<controller>
<variable name="item" mapped-name="Item" access="read,write" />
<variable name="quantity" mapped-name="Quantity" access="read,write" />
<variable name="address" mapped-name="Address" access="read,write" />
</controller>
</task>
<transition to="Evaluate web order" />
</start-state>

Would have generated a form. But *not* like the one in the jBPM 3.2 websale example. The major difference being that the custom form in the example contains code to specify that the quantity input should be an integer

<h:inputText value="#{var['quantity']}" converter="javax.faces.Integer" converterMessage="The quantity must be numeric." validatorMessage="The quantity must be at least 1.">
<f:validateLongRange minimum="1"/>
</h:inputText>

Both solutions have advantages but also the disadvantage that it did not support the functionality of the other and both could not take the type into account (since it could not be specified at all) making every input a string . The design-time generated forms at least let you adapt those manually. Loosing those changes when a variable was added and the form regenerated. Now you know jBPM is extensible in the xml definition, putting a type on the variable would have been an option without changing the persistence class of the variable instance. Creating a template with conditional rendering, a custom jsf var list bean and some small other changes, would have given you the automagically generated form which does take the type into account:

<jbpm:dataform>

<f:facet name="header">
<h:outputText value="#{taskName}"/>
</f:facet>

<!-- TASKFORM ROWS -->
<c:forEach items="#{vars}" var="var">

<jbpm:datacell>

<f:facet name="header">
<h:outputText value="#{var.name}"/>
</f:facet>

<h:inputText value="#{var.value}" rendered="#{var.type == 'String'}"/>
<h:inputText value="#{var.value}" rendered="#{var.type == 'Integer'}" converter="javax.faces.Integer" converterMessage="Must be numeric."
</h:inputText>
<rich:calendar value="#{var.value}" rendered="#{var.type == 'Date'}"/>


</jbpm:datacell>

</c:forEach>

</jbpm:dataform>

This is just one example. You could also have changed the composite access attribute to the more logical separate ‘readOnly’ and ‘required’ attribute (the write only never made real sense to me in real life) and if you continue, why not put validation patterns in there, error messages, and what more. In the end you could almost as well have put the .xhtml form fragement in there as a nested element (you could… I’m not kidding).

Personally, I never went this way, not even putting in just the type in the variable definition. Then why this post you might ask. Well, I just wanted to describe the  concept of this extensibility and I did use it but in a completely different way. More on this in a later post

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: