Within the Imixs-Workflow project we started our first sample application based on the new Jakarta EE web framework MVC 1.0. The sample application demonstrates how an Imixs-Workflow application can be build with MVC 1.0.
The interesting thing here is that you only need a few lines of code to get the full functionality of a human-centric workflow engine. This is possible because in addition to the existing Jax-rs Rest API, the Imixs-Workflow engine provides services which can be easily adapted by the core concepts of an MVC-Application.
Value Binding
Of course MVC 1.0 supports the concept of separation between the model and the view. With the help of the expression language (EL), you can easily bind the values form a model to an input field.
<input type="text" value="#{mymodel.property}" />
The Imixs-Workflow project provides the generic value object “org.imixs.workflow.ItemCollection“. This object is used to represent workflow data over all layers within this project. An ItemCollection stores Item-Value pairs and provides various setter- and getter-methods to access the item values. You can use this object in a CDI Model to easily exchange data between the web framework and the workflow engine. The following example show a typical MVC CDI-Model object with a data property called ‘workitem’ from the type ItemCollection.
@RequestScoped @Named public class Model implements Serializable { private static final long serialVersionUID = 1L; ItemCollection workitem; public ItemCollection getWorkitem() { return workitem; } public void setWorkitem(ItemCollection workitem) { this.workitem = workitem; } }
The CDI Model can be injected into a MVC Controller which fills the model with data. The data can than be accessed by a view:
<dl> <dt>Name:</dt> <dd> <input type="text" value="#{model.workitem.item['_subject'}}" name="_subject" /> </dd> </dl>
Note: You should not access the MVC Controller directly form your view.
The concept of a generic value object makes it very easy and flexible to build web front-ends. You do not need to define each property manually in your model.
Processing Form Data
There is also an easy way to process the form data. The Imixs-Workflow project provide a method to parse the data from a form submit. The method converts the data into a ItemCollection. In this way the data can directly be processed by the WorkflowService. The following example shows how a MVC Controller POST method is implemented:
@Inject Model model; @EJB WorkflowService workflowService; .... @POST @Path("{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}") @Consumes({ MediaType.APPLICATION_FORM_URLENCODED }) public String processTicket(@PathParam("uniqueid") String uid, InputStream requestBodyStream) { try { // parse and process the form data. ItemCollection workitem = WorkflowRestService.parseWorkitem(requestBodyStream); workitem.replaceItemValue(WorkflowKernel.UNIQUEID, uid); workitem = workflowService.processWorkItem(workitem); model.setWorkitem(workitem); } catch (AccessDeniedException | ProcessingErrorException | PluginException | ModelException e) { ... } .... }
The path param ‘uniqueid’ in this example is the identifier of a process instance managed by the Imixs-Workflow engine. The controller consumes an InputStream with the data from a form submit. This data is converted into an ItemCollection and than processed by the WorkflowService. With this implementation there is no need to define a @FormParam for each input field in your processing method. Of course you can do this if you like to validate data. The Imixs-Workflow project provides a plug-in concept to validate and process the data independent form the front-end framework.
Return Types and Redirects
The second interesting part in integrating Imixs-Workflow into a MVC 1.0 Application is the evaluation of an action result defined by the workflow model. A MVC 1.0 controller method with the return type String is typically used to define the corresponding view outcome. So for example a GET method in a MVC controller can look like this:
@GET public String actionHome() { .... return "home.xhtml"; }
In this example the form outcome is hard coded by the controller method ‘actionHome’ and renders the page ‘home.xhmlt’.
With Imixs-Workflow the business logic of an application is defined by BPMN 2.0 model.
When a event is triggered the workflow engine updates the status of an existing or newly created process instance. One feature of Imixs-Workflow is the definition of a workflow action result.
A workflow action result can be used to compute the outcome of a MVC 1.0 controller based on the workflow model. This gives a lot of additional flexibility to control the application behavior. In the following example shows how the action result is evaluated by the MVC controller POST method:
@POST @Path("{uniqueid : ([0-9a-f]{8}-.*|[0-9a-f]{11}-.*)}") @Consumes({ MediaType.APPLICATION_FORM_URLENCODED }) public String processTicket(@PathParam("uniqueid") String uid, InputStream requestBodyStream) { ... workitem = workflowService.processWorkItem(workitem); return workitem.getItemValueString("action"); }
Conclusion
MVC 1.0 is a modern action based web framework which fits perfectly into the concept of the human based workflow engine Imixs-Workflow.
Unlike JSF, MVC pursues a more consistent way to keep the front-end logic simple. By aligning with Jax-RS, existing Rest APIs can be easily adapted. In our sample application we demonstrate how the Imixs-Workflow engine can be integrated into an MVC application. In the near future, we will certainly publish an Imixs-MVC library to make integration even easier.