Bussinessanwendungen mit Imixs-Workflow

Imixs Workflow ist ein open Source Framework für die Erstellung von Geschäftsanwendungen. Mit Hilfe der Imixs Workflow Engine können relativ schnell leistungsfähige Anwendungen realisiert werden in denen die Umsetzung von Geschäftsprozessen im Vordergrund steht. Typische Beispiele in denen sich der Einsatz einer Workflow Engine lohnt sind Genehmigungs- und Freigabeprozesse oder allgemein Geschäftsprozesse in denen mehrerer Akteure beteiligt sind. Über das Workflow Modell wird festgelegt welche Zustände ein Vorgang haben kann und welche Aktionen in den jeweiligen Zuständen erlaubt  sind. Die Workflow Engine verwaltet die einzelnen Prozessinstanzen und kümmert sich um das Routing zwischen den einzelnen Akteuren innerhalb des Geschäftsprozesses.   Ein Imixs Workflow Modell kann über Eclipse mit dem Imixs Modeller schnell erstellt werden. Im Gegensatz zu einer BPMN Modellierung geht es hier nicht darum, die einzelnen Tasks zu modellieren, sondern die Zustände in denen sich der Geschäftsprozess befinden kann. Welche Aktivität der Benutzer letztlich wählt wird nicht von der Workflow Engine beeinflusst. Diese kümmerst sich lediglich darum das der Geschäftsprozess in den nächsten Zustand (Zustandsdiagramm) versetzt wird und einzelne Aktionen die den Prozess unterstützen korrekt ausgeführt werden. Hierzu zählen zum Beispiel:

  • Versandt einer E-Mailnachricht an den nächsten Bearbeiter
  • Aktualisierung der Lese- und Schreibrechte der aktuellen Prozessinstanz
  • Aktualisierung von Aufgabenlisten der einzelnen Akteure
  • Aktualisierung der Vorgangshistorie

Das Workflow Management System kümmerst sich also darum, wer wann welche Aufgabe zu erledigen hat.

Integration in eine Java Enterprise Anwendung

Imixs Workflow basiert auf dem Java Enterprise Standard (JEE 6). Dadurch kann die Imixs Workflow Engine relativ einfach als Business Komponente in eine neue oder bereits bestehende Anwendung aufgenommen werden. Eine Beispielanwendung stellt das Imixs Projekt auf GitHub bereit. Diese Anwendung kann auch als Grundlage für eigene Projekte genutzt werden. Um die Imixs-Workflow Engine in eine JEE Anwendung zu integrieren sind folgende Schritte notwendig:

1.) Bereitstellung eines EJB Moduls

Die Imixs Workflow Engine ist als stateless Session EJB realisiert. Ach andere Komponenten des Projekts stehen als EJBs zur Verfügung. Nach dem die Bibliotheken imixs-workflow-engine.jar und  imixs-workflow-core.jar in das eigene Projekt hinzugefügt wurden (z.b. unter /WEB-INF/lib/) muß eine ejb-jar.xml Datei und eine persistence.xml Datei ergänzt werden um die Komponenten zu aktivieren. Die ejb-jar-xml Datei kann in einem Web Projekt unter /WEB-INF/ zusammen mit der web.xml Datei abgelegt werden.

Der Aufbau ist relativ einfach, da hier lediglich die Mail Ressource für den Versandt von Emails angegeben werden muss:

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://java.sun.com/xml/ns/javaee" xmlns:ejb="http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
 version="3.0">
<enterprise-beans>

<session>
 <ejb-name>WorkflowService</ejb-name>
 <ejb-class>org.imixs.workflow.jee.ejb.WorkflowService</ejb-class>
 <session-type>Stateless</session-type>
 <!-- Mail Configuration -->
 <env-entry>
 <description> Mail Plugin Session name</description>
 <env-entry-name>IMIXS_MAIL_SESSION</env-entry-name>
 <env-entry-type>java.lang.String</env-entry-type>
 <env-entry-value>mail/org.imixs.workflow.mail</env-entry-value>
 </env-entry>
 <resource-ref>
 <res-ref-name>java:/mail/org.imixs.workflow.mail</res-ref-name>
 <res-type>javax.mail.Session</res-type>
 <res-auth>Container</res-auth>
 <res-sharing-scope>Shareable</res-sharing-scope>
 </resource-ref>
</session>
</enterprise-beans>
</ejb-jar>

Zusätzlich muss die Datei persistence.xml bereitgestellt werden. Bei Web Anwendungen liegt diese unter WEB-INF/classes/META-INF/.
Die persistence.xml Datei definiert die JPA Datenquelle in der die Workflow Engine ihre Prozessinstanzen ablegt.

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence">

 <jta-data-source>jdbc/workflow-db</jta-data-source>
 <jar-file>lib/imixs-workflow-engine-3.1.7.jar</jar-file>
 <properties>
 <property name="eclipselink.ddl-generation"
 value="create-tables" />
 <property name="eclipselink.logging.level" value="INFO"/>
 </properties> 
 </persistence-unit>
 
</persistence>

Hier ist es wichtig das das jar-file exakt der bereitgestellten Version der Imixs Workflow Engine entspricht. Der eigentliche JDBC Datenbank Pool kann nun unabhängig auf dem Applikationsserver unter dem Namen ‘jdbc/workflow-db’ eingerichtet werden. Dabei kann selbstverständlich jede gängige SQL Datenbank eingesetzt werden.

2.) Einrichten eines Security Realms

Alle Zugriffe auf die Imixs-Workflow Engine laufen authentifiziert ab. D.h. der Benutzer muss zuvor am System angemeldet sein, bevor er auf Aufgaben zugreifen kann, oder ggf. selbst neue Workflow startet. Dazu muß ein sogenannte security realm erzeugt werden. Dieser wird zusammen mit der JDBC Datenbank auf dem Applikationsserver eingerichtet.

Der Security Realm wird bei GlassFish Anwendungen unter /WEB-INF/glassfish-web.xml eingerichtet unter WildFly in /WEB-INF/geronimo-web.xml.

glassfish-web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app>

 <context-root>/workflow</context-root>

 <security-role-mapping>
 <role-name>org.imixs.ACCESSLEVEL.NOACCESS</role-name>
 <group-name>Noaccess</group-name>
 <group-name>IMIXS-WORKFLOW-Noaccess</group-name>
 </security-role-mapping>

 <security-role-mapping>
 <role-name>org.imixs.ACCESSLEVEL.READERACCESS</role-name>
 <group-name>Reader</group-name>
 <group-name>IMIXS-WORKFLOW-Reader</group-name>
 </security-role-mapping>

 <security-role-mapping>
 <role-name>org.imixs.ACCESSLEVEL.AUTHORACCESS</role-name>
 <group-name>Author</group-name>
 <group-name>IMIXS-WORKFLOW-Author</group-name>
 </security-role-mapping>

 <security-role-mapping>
 <role-name>org.imixs.ACCESSLEVEL.EDITORACCESS</role-name>
 <group-name>Editor</group-name>
 <group-name>IMIXS-WORKFLOW-Editor</group-name>
 </security-role-mapping>

 <security-role-mapping>
 <role-name>org.imixs.ACCESSLEVEL.MANAGERACCESS</role-name>
 <group-name>Manager</group-name>
 <group-name>IMIXS-WORKFLOW-Manager</group-name>
 </security-role-mapping>
</glassfish-web-app>

geronimo-web.xml:

<web-app xmlns="http://geronimo.apache.org/xml/ns/j2ee/web-2.0"
 xmlns:sec="http://geronimo.apache.org/xml/ns/security-2.0" xmlns:cfg="http://geronimo.apache.org/xml/ns/deployment-1.2">

 <context-root>/workflow</context-root>
 <security-realm-name>imixsrealm</security-realm-name>
 <sec:security>
 <sec:role-mappings>
 <sec:role role-name="org.imixs.ACCESSLEVEL.MANAGERACCESS">
 <sec:principal
 class="org.apache.geronimo.security.realm.providers.GeronimoGroupPrincipal"
 name="IMIXS-WORKFLOW-Manager" designated-run-as="true" />
 </sec:role>
 </sec:role-mappings>
 </sec:security>

</web-app>

Diese Dateien dienen dazu die Benutzer Rollen auf die JEE Rollenbezeichnungen der Imixs Workflow Engine zu mappen.

3.) Konfiguration der REST API

Als letztes wird nun noch ein REST Schnittstelle für den Zugriff auf die Imixs-Workflow Engine eingerichtet. Dies erfolgt wieder über die web.xml Datei.

Hier ein Beispiel aus einer GlassFish Anwendung. Es wird sowohl das Servlet für den REST Service konfiguriert, als auch das Security Mapping eingerichtet:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
 <display-name>Imixs Sample Web Application</display-name>
 <welcome-file-list>
 <welcome-file>pages/welcome.xhtml</welcome-file>
 </welcome-file-list>
 <context-param>
 <param-name>javax.faces.PROJECT_STAGE</param-name>
 <param-value>Development</param-value>
 </context-param>
 <servlet>
 <servlet-name>Faces Servlet</servlet-name>
 <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
 <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
 <servlet-name>Faces Servlet</servlet-name>
 <url-pattern>*.jsf</url-pattern>
 </servlet-mapping>
 <servlet-mapping>
 <servlet-name>Faces Servlet</servlet-name>
 <url-pattern>*.xhtml</url-pattern>
 </servlet-mapping>
 <servlet>
 <servlet-name>ImixsRestService</servlet-name>
 <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
 <init-param>
 <param-name>com.sun.jersey.config.property.packages</param-name>
 <param-value>org.imixs.workflow.jaxrs</param-value>
 </init-param>
 <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
 <servlet-name>ImixsRestService</servlet-name>
 <url-pattern>/rest/*</url-pattern>
 </servlet-mapping>
 <login-config>
 <auth-method>BASIC</auth-method>
 <realm-name>ApplicationRealm</realm-name>
 </login-config>
 <security-constraint>
 <web-resource-collection>
 <web-resource-name>restricted</web-resource-name>
 <url-pattern>/pages/*</url-pattern>
 <url-pattern>/rest/*</url-pattern>
 <http-method>GET</http-method>
 <http-method>POST</http-method>
 </web-resource-collection>
 <auth-constraint>
 <role-name>org.imixs.ACCESSLEVEL.READERACCESS</role-name>
 <role-name>org.imixs.ACCESSLEVEL.AUTHORACCESS</role-name>
 <role-name>org.imixs.ACCESSLEVEL.EDITORACCESS</role-name>
 <role-name>org.imixs.ACCESSLEVEL.MANAGERACCESS</role-name>
 </auth-constraint>
 </security-constraint>
 <security-constraint>
 <web-resource-collection>
 <web-resource-name>restricted</web-resource-name>
 <url-pattern>/RestService/*</url-pattern>
 <http-method>GET</http-method>
 <http-method>POST</http-method>
 <http-method>PUT</http-method>
 </web-resource-collection>
 <auth-constraint>
 <role-name>org.imixs.ACCESSLEVEL.MANAGERACCESS</role-name>
 </auth-constraint>
 </security-constraint>
 <security-role>
 <role-name>org.imixs.ACCESSLEVEL.NOACCESS</role-name>
 </security-role>
 <security-role>
 <role-name>org.imixs.ACCESSLEVEL.READERACCESS</role-name>
 </security-role>
 <security-role>
 <role-name>org.imixs.ACCESSLEVEL.AUTHORACCESS</role-name>
 </security-role>
 <security-role>
 <role-name>org.imixs.ACCESSLEVEL.EDITORACCESS</role-name>
 </security-role>
 <security-role>
 <role-name>org.imixs.ACCESSLEVEL.MANAGERACCESS</role-name>
 </security-role>
</web-app>

Beim Einsatz von WildFly wird eine andere JAX-RS Implementierung verwendet so dass hier die Servlet Konfiguration wie folgt aussehen muss:

 <context-param>
 <param-name>resteasy.scan</param-name>
 <param-value>true</param-value>
 </context-param>
 <context-param>
 <param-name>resteasy.servlet.mapping.prefix</param-name>
 <param-value>/rest</param-value>
 </context-param>
 <listener>
 <listener-class>
 org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
 </listener-class>
 </listener>
 <servlet>
 <servlet-name>ImixsRestService</servlet-name>
 <servlet-class>
 org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
 </servlet-class>
 </servlet>

Danach kann der Zugriff auf die Imixs-Workflow Engine schon getestet werden.  Über die REST API kann das Modell geprüft werden:

http://localhost:8080/workflow/rest/model

Mit dieser URL kann nun auch über den Imixs-Modeller ein eigenes Modell hochgeladen werden.

Weitere Informationen zur Programmierung gibt es hier:

  • http://www.imixs.org/jee/examples/workflowmanager.html
  • http://www.imixs.org/modeler/
  • http://www.imixs.org/api/