For version 2.1.2
Copyright © 2002, 2003, 2004, 2005, 2006, 2007 Danet GmbH
All rights reserved.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Table of Contents
List of Figures
List of Tables
This document describes how to integrate and use Danet's J2EE based workflow component. The Maintenance Guide describes the internal structures and design principles of the component.
Danet's workflow component is a J2EE based implementation of a workflow facility (workflow engine) as proposed by the Workflow Management Coalition (WfMC) and the Object Management Group (OMG).
The workflow component includes and is based on a set of JAVA interfaces that define an API for a workflow management facility. These "omgcore" interfaces follow OMG's Workflow Management Facility Specification, V1.2 very closely, while making some changes to adapt the CORBA service to the established design practices for a Java API.
Danet's workflow component provides a collection of EJBs that implement the omgcore interfaces together with some additional interfaces for tasks not covered by the OMG specification. The EJBs are provided as a J2EE module that can be used in any J2EE compliant application server.
The workflow engine is designed as a J2EE component. It is intended to be integrated in an application that requires a workflow engine. As a proof of concept and test environment, we provide a demo application. The demo application consists of the workflow component and some additional modules with a portal based GUI. Combined they provide a small workflow system that may be used to get acquainted with the workflow engine. You can find more information about this demo application in Appendix C, The demo applications
This manual assumes that you are familiar with Sun's Java™ 2 Platform Enterprise Edition Specification, v1.2.
describes all steps required to integrate the workflow component in an application.
describes all defined and supported states and state transitions of processes and activities.
gives an inside view of the internal structure of Danet's workflow component.
helps managing process definitions.
lists the tools available in this workflow component. Tools are applications that can be started from an activity.
shows how to develop or integrate a resource assignment service with the help of a simple example.
lists the bugs and limitations of the workflow component currently known.
describes the java user interface of the workflow components in javadoc format.
gives an inside view of the provided demo applications.
The following conventions will be applied throughout this document:
name
to state a common name or id as it is used within the workflow component.
package
for package name.
class
for class names.
variable
to describe a name of a variable.
Table of Contents
The workflow engine is designed as a component. Therefore the typical usage is to integrate it into your application. The following sections describe the steps required to do this. If you want to get acquainted with the workflow engine by installing a demo application, please proceed to Appendix C, The demo applications. If you want to experiment with the API, step by step instructions how to build a basic sample client can be found in Section 3.3, “Sample client”. If you want to integrate the workflow component with your application or understand its structure, continue reading here.
The binary distribution comes as an installer. In the simplest
case, the installer only copies the libraries and documentation to your
filesystem. It provides, however, additional operations to configure your
application server and initialize a database. The installer is
distributed as an executable jar. It is invoked as "java -jar
wfmopen-".
n.m-installer.jar
The figures below show the installer screens for copying the components to the filesystem.
$DIST
represents the top level directory of the
binary distribution, i.e. the installation directory that you have
specified in the dialog above.
WfMOpen requires JDK 1.4.2 (see Section 1.3.7, “Additional libraries” for more details). Older JDK versions back to 1.3 may work, tests have, however, only been made with JDK 1.4.2_15 and JDK 1.6.0_02.
The workflow component requires a database that supports distributed transactions. WfMOpen relies on operations on queues and on the database being made in a single transaction. This can only be accomplished by using distributed transactions[1]. If you are looking for an OpenSource solution, we recommend using MAXDB (formerly known as SAPDB).
The workflow component relies on the presence of a number of
tables in a database. The table definitions are provided as file
$DIST/lib/wfdemo/database/. The
files contain SQL statements that can be executed by appropriate
database tools.
RDBMS-type/create.sql
If you cannot find scripts for your database, you can still use
the generic table definition in
$DIST/lib/wfdemo/database/database-schema.xml. It
is suited to be processed by the Apache DDLUtils (see Apache DDLUtils
site)[2].
As an alternative, the schema can be created by the installer. In order to do this, choose the option "(Re-)create schema" as shown below.
The installer then uses the DDLUtils to create the schema in your database. This will work for all databases that are supported by DDLUtils.
The workflow component software consists of several JAR files (modules and libraries) that have to be assembled into a J2EE application or have to be included in the classpath of a client. The figure shows an overview of the JAR files and their usage.
The specified workflow APIs (packages
de.danet.an.workflow.omgcore
and de.danet.an.workflow.api,
see Section 3.2, “Client API”) are packaged in a
separate jar de.danet.an.wfcore-apis.jar
located in the distribution directory
$DIST/lib/wfcore. Only this JAR file should
be used in the classpath when compiling clients. Consequently,
it must also be included in the runtime classpath of a client.
The runtime-classes needed by a client that wants to use the
workflow component are provided as
de.danet.an.wfcore-client.jar in
$DIST/lib/wfcore. This JAR file is not self
contained, i.e. it relies on the presence of the workflow APIs
(de.danet.an.wfcore-apis.jar), the Danet AN
utility classes (de.danet.an.util.jar, see
following section) and the additional libraries described in Section 1.3.7, “Additional libraries”. In addition, the client needs some
information about how to contact the server. See the description of the
basic WorkflowServiceFactory (in Section A.2.52, “Class WorkflowServiceFactory”), the
description of the WfMOpen specific factory implementation (in de.danet.an.workflow.ejbs.client.StandardWorkflowServiceFactory)
and the remarks in Section 1.3.4, “Workflow module” below.
All J2EE based software from the division AN uses a library with
some common utility objects and components. This library is
supplied as de.danet.an.util.jar (again
located in the $DIST/lib/wfcore). Some
components in this library (currently the logging service) need
server side support. This support is provided by the
corresponding EJB module described below.
The Danet AN utility library (package
de.danet.an.util) is a general
library used at our site. This library is packaged as two JAR
files. By default, classes are in
de.danet.an.util.jar. Some classes in the
package (sub-package
de.danet.an.util.jsf),
however, are helper classes for JSF based portlets. These
classes are are not included in
de.danet.an.util.jar. They can be found in
de.danet.an.util-jsf.jar. The reason for
separating those classes is that they may not be put in the
common classpath of a J2EE application. In order to avoid
classpath problems, you have to put these JSF utility classes
in the same directory as the JSF libraries (usually the
WEB-INF/lib directory of your
web module). Note that the classes from
de.danet.an.util.jsf are
only needed by the portlets that come with the
workflow component. The deployment of the workflow EJBs requires
de.danet.an.util.jar only.
The central (server side) workflow component is an EJB-type J2EE
module. This module is not self contained, i.e. it relies on the
presence of the workflow APIs, the Danet AN utility library and
the additional libraries listed below. The module is located in
the distribution directory $DIST/lib/wfcore
as de.danet.an.wfcore-ejbs.jar.
The manifest file of
de.danet.an.wfcore-ejbs.jar includes in its
Class-Path: statement the entries
lib/de.danet.an.wfcore-apis.jar and
lib/de.danet.an.util.jar. Thus, the
dependencies between the workflow module, the workflow APIs and
the Danet AN utility library will be resolved automatically if
de.danet.an.util.jar is put in the
lib/ directory of the enterprise archive
(the .ear-file). An additional
Class-Path: entry
lib/de.danet.an.wfcore-plugins.jar serves
as a hook for adding jars with tool agents (see Section 3.5, “Tool invocation SPI”) to the class path. We recommend to
put new tool agents or other libraries that are to be deployed
with the engine core in extra add-on jar files. Then create a
jar de.danet.an.wfcore-plugins.jar with
only a META-INF/MANIFEST.MF that references
your jars in its Class-Path: entry and add
this (along with your add-on jars) to the EAR as
lib/de.danet.an.wfcore-plugins.jar. The
application server will then load
de.danet.an.wfcore-plugins.jar (because it
is referenced in
de.danet.an.wfcore-ejbs.jar) and
subsequently your jars with additional components.
The file de.danet.an.wfcore-ejbs.jar
includes vendor specific deployment descriptors for some
application servers. These deployment descriptors define,
among other things, the binding of EJBs (EJB's home
interfaces, to be precise) to global JNDI
names[3]. As the workflow engine is
intended to be integrated in different applications that may
run on one application server concurrently, the JNDI names
must be adapted to the specific application the engine is
integrated with; else there will be conflicts between the
applications. All deployment descriptors therefore use
"generic" names for JNDI bindings such as
"ejb/@@@_JNDI_Name_Prefix_@@@SomeEJB".
When packing the workflow engine EJBs, the prefix
"@@@_JNDI_Name_Prefix_@@@"
should be replaced with some reasonable value (e.g.
""@@@_JNDI_Name_Prefix_@@@ =
de.danet.wfdemo.").
Whereever the workflow module references the utility module (see Section 1.3.6, “The utility module”) in the included vendor specific deployment descriptors, it uses the same symbolic names as the deployment descriptors of the utility module (again, see Section 1.3.6, “The utility module”). These symbolic names must be adapted as well when assembling an application.
Note that "generic" names and "symbolic" names for resources appear only in vendor specific deployment descriptors. So supplying your own vendor specific deployment descriptors from scratch is an alternative integration strategy.
The workflow module includes Ant helper scripts for executing the required adaptions. See Section 1.4.1, “Preparing the modules” for details.
One global JNDI name is of specific importance. It is the name
of the
WorkflowEngineEJB. This EJB
is the only EJB looked up directly in JNDI by a workflow
engine's client (remote interfaces of other EJBs are passed to
the client directly or indirectly by methods of the
WorkflowEngineEJB). Therefore,
the global JNDI name of the
WorkflowEngineEJB's home
interface must be made known to the client. The lookup of this
home interface need not be made explicitly. Rather, it is
encapsulated in the creation of a new workflow service by the
WorkflowServiceFactory (see
newWorkflowService()).
Thus the configuration of the JNDI name becomes a
configuration issue of WfMOpen's implementation of the
WorkflowServiceFactory. WfMOpen's
implementation class and its configuration is described in
detail in de.danet.an.workflow.ejbs.client.StandardWorkflowServiceFactory.
The preferred way to do the configuration[4] is to first create a
file de.danet.an.workflow-wfs.properties
with an entry engine =
ejb/@@@_JNDI_Name_Prefix_@@@WorkflowEngine
(applying the replacement described above) and then to add
this file to the client JAR
de.danet.an.wfcore-client.jar. This
results in an "application specific" client library. Anywhere
this client JAR is used, the resource
de.danet.an.workflow-wfs.properties is
found by the
StandardWorkflowServiceFactory
in the JAR and the proper workflow engine EJB is looked up.
Another value that may need replacement is the security
domain. The JBoss vendor specific deployment descriptor
defines the security domain as
java:/jaas/wfmopen. This
should be replaced by the application's domain.
In addition to the EJBs and the libraries, the workflow module
requires three queues to be defined. By default, the JNDI
names of these queues are
"queue/@@@_JNDI_Name_Prefix_@@@ApplicationInvocations",
"queue/@@@_JNDI_Name_Prefix_@@@InternalEventQueue"
and
"topic/@@@_JNDI_Name_Prefix_@@@EventService",
with the latter being a topic queue. These names are
referenced in the vendor specific deployment descriptors of
the EJBs and must be adapted with the prefix replacement as
described above.
You can find sample definitions of the required queues for
JBoss in
$DIST/lib/wfcore/wfcore-destinations-service.xml. Depending
on your application server, you have to created these queues
before the deployment of your application using e.g. some
console application. Alternatively, you may usually trigger
the creation and configuration of the queues by adding some
vendor specific information to your enterprise archive (this
mechanism is used in the demo applications, see Appendix C, The demo applications).
The workflow module as distributed uses in its deployment descriptors a predefined security role "WfMOpenAdmin" as only role and this role has all permissions[5].
The actual work during process execution is done by tool agents (see Section 3.5, “Tool invocation SPI”). Several of these tool agents are included in WfMOpen (see Chapter 5, Tools). Usually projects will add their own specific tool agents. In simple deployment scenarios, this can easily be done by adding jars with tool agent implementations as described above in Section 1.3.4, “Workflow module”.
In more complex deployment scenarios, there is a drawback to this approach. Consider an application with a core EAR that contains, among other components, WfMOpen. Other EARs provide additional services. In order to invoke these services from the workflow engine with specific tool agents, the agents would have to be bundled with the core EAR. But this would create a dependency on services and classes in the additional EAR and thus effectively a circular dependency. It would also be hard to have a consistent application server startup. If the engine is deployed first it may try to invoke a tool agent that requires services from an EAR that is not completely deployed yet.
In order to support such deployment scenarios, WfMOpen provides
the callback module
de.danet.an.wfcore-callback-ejbs.jar that
may be bundled with the additional service EARs and executes
tool agent invocations in the context of these service EARs. The
callback module bundles two EJBs that are also contained in the
core workflow module: an EJB that reads messages from the
application invocation queue and an EJB (the
InvocationHelperEJB) that invokes the tool
agents. Tool agent invocations are forwarded to callback EJBs by
specifying a Handler attribute for the
application declaration in the process definition (see Section 4.2.5.1, “Extentions of Application Declaration”). Configuring the callback module is
described in Section 1.4.4, “Callback module deployment”.
As described above, all J2EE based software from the division AN
uses some common utility objects and components. While most of
these elements can be simply supplied as a library, some
components (currently the logging support) consist of a client
and a server part. The J2EE server side elements are packaged in
the distinct EJB-type J2EE module
de.danet.an.util-ejbs.jar that is also
located in the $DIST/lib/wfcore
distribution directory. This module must be deployed along with
the workflow module.
As the utility module is intended to be used in several applications, we have deliberately not defined defaults for some information needed during deployment. Providing defaults for these values would imply the risk that different applications inadvertently access each others utility EJBs. Instead of defaults we use symbolic names in the deployment descriptors that can reliably be replaced automatically.
All symbolic names are described below. The description should be sufficient to allow you to adapt the deployment descriptors for your application. For more information about these EJBs, see the maintenance manual.
The symbolic names used are:
@@@_Utility-EJBs_UtilEJB_JNDI_Name_@@@
The utility EJB's global JNDI name. This EJB has a
global JNDI name defined because it may be needed by
stand-alone clients. A reasonable value if the utility
module is used in a workflow application would be
de.danet.an.workflow.util-lib.Util.
@@@_Utility-EJBs_KeyGenEJB_JNDI_Name_@@@
The key generator EJB's global JNDI name. The key
generator EJB has a global JNDI name defined because it
may be needed by stand-alone clients. A reasonable value
if the utility module is used in a workflow application
would be
de.danet.an.workflow.util-lib.KeyGen.
@@@_Utility-EJBs_EJBSinkEJB_JNDI_Name_@@@
The log4j EJB-appender's global JNDI name. This EJB has
a global JNDI name defined because it may be needed by
stand-alone clients. A reasonable value if the utility
module is used a workflow application would be
de.danet.an.workflow.util-lib.EJBSink.
As distributed, the utility module's descriptors do not specify any security constraints. We do, however, strongly recommend adding such constraints as appropriate for an application's security domain when assembling the application[6]. A common configuration is to introduce the same security role as used for the workflow engine EJBs (i.e. "WfMOpenAdmin", see Section 1.3.4, “Workflow module”) and allow this role to execute all methods.
The module includes support for executing the required adaptions. See Section 1.4.1, “Preparing the modules” for details.
As is usually the case with complex Java applications, the workflow component needs some third party libraries in addition to the standard JDK. Those libraries are:
The commons-logging library from the Apache Jakarta Project (for server).
The log4j library from the Apache Group (for client and server).
The jdom library (for server).
The dom4j-full library (for server). This library also supplies the jaxen libraries.
The jsr173 (a.k.a StAX) library (for server and client).
The Rhino (JavaScript) library (for server).
The XMLBeans library (for server). This library is required by Rhino for the E4X support.
The jelly core, xml-tags and jsl-tags libraries (for server).
The BeanUtils library (for server, needed by jelly).
The axis library (for server).
When you want to use WfMOpen with JDK/JRE 1.4, updated versions
of the JRE XML packages (org.w3c.dom,
org.xml.sax,
org.xml.sax.ext and
org.xml.sax.helpers) are needed. You you must
therefore use the
Endorsed Standards Override Mechanism of the JDK to
provide those newer versions, i.e. you have to set the system
property java.endorsed.dirs to the
directory
$DIST/lib/wfdemo/endorsed[7]. For the versions of the
XML libraries currently used see the CVS information in the
tools/endorsed subdirectory.
As has been described in the previous sections, the deployment
descriptors of the EJB modules must be adapted to the
application that integrates the workflow engine. In order to
facilitate this task, the EJB JARs have in their subdirectory
assembly-resources ant scripts with targets
that may be called to perform the adaption. Of course, these
scripts do not have to be used to adapt the EJBs, they are
simply provided as useful helpers.
File assembly-resources/assembly-utils.xml
provides general
purpose targets that can be used for any EJB JAR, not only for
the workflow engine or utility EJBs.
add-ejb-resource-ref
Add a resource reference to an EJB. Must be called with properties "src-ejb-jar=<the ejb jar to patch>", "target-ejb-jar=<the patch result>", "ejb-name=<the ejb that references the resource>", "ref-name=<the locigal name used by the EJB to reference the resource>", "jndi-name=<the (global) JNDI entry for the resource>", "res-auth" and "res-type" as to be put into the ejb-jar.xml. This target needs additional resources (DTDs and stylesheets) that must be provided in a directory specified with property "resource-dir=<directory>".
add-remote-ejb-resource-ref
Add a reference to a remote EJB. Must be called with properties "src-ejb-jar=<the ejb jar to patch>", "target-ejb-jar=<the patch result>", "ejb-name=<the ejb that references the remote ejb>", "ref-name=<the locigal name used by the EJB to reference the resource>", "ref-type=<Session or Entity>", "home", "remote" and "link" as to be put into the ejb-jar.xml. This target needs additional resources (DTDs and stylesheets) that must be provided in a directory specified with property "resource-dir=<directory>".
add-local-ejb-resource-ref
Add a resource reference to a local EJB. Must be called with properties "src-ejb-jar=<the ejb jar to patch>", "target-ejb-jar=<the patch result>", "ejb-name=<the ejb that references the resource>", "ref-name=<the locigal name used by the EJB to reference the resource>", "ref-type=<Session or Entity>", "local-home", "local" and "link" as to be put into the ejb-jar.xml. This target needs additional resources (DTDs and stylesheets) that must be provided in a directory specified with property "resource-dir=<directory>".
adapt-ejb-jar
Modify the deployment descriptors of an ejb jar by replacing given strings with other strings as specified in a properties file. Must be called with properties "src-ejb-jar=<filename of distributed ejb jar>", "target-ejb-jar=<filename of adapted ejb jar>" and "props=<filename with properties>". If the special properties "security-roles", "security-identities" and "security-domain" are defined, security information will additionally be inserted into the deployment descriptors as specified by these properties. This target needs additional resources (DTDs and stylesheets) that must be provided in a directory specified with property "resource-dir=<directory>". This target also removes the sub-directory "assembly-resources" from the ejb jar if such a sub-directory exists. An additional properties file may be specified as property "token-replacements". The replacements specified in this file are applied to all deployment descriptors first. It is useful if you want to process the same EJB twice, using one replacement from your main properties file in the first step and another replacement in the second step, or to simply override replacements in the main properties file.
add-ejb-env-entry
Add a resource reference to an EJB. Must be called with properties "src-ejb-jar=<the ejb jar to patch>", "target-ejb-jar=<the patch result>", "ejb-name=<the ejb that requires the entry>", and "env-entry-name=<name of environment entry>", "env-entry-type=<type of environment entry>" and "env-entry-value=<value of environment entry>". The target needs additional resources (DTDs, schemas and "assembly-utils.xml") which must be provided in a directory specified with property "resource-dir=<directory>".
adapt-war
Modify the deployment descriptors of a war by replacing given strings with other strings as specified in a properties file. Must be called with properties "src-war=<filename of distributed war>", "dest-war=<filename of adapted war>" and "props=<filename with properties>". An optional property "libs-to-remove" may be set to a comma separated list of files to remove from WEB-INF/lib (because they will be supplied by the containing EAR).
add-env-entry-to-servlet
Modify the deployment descriptors of a war by adding an environment entry. Must be called with properties "src-war=<filename of distributed war>", "dest-war=<filename of adapted war>" and "env-entry-name=<name of environment entry>", "env-entry-type=<type of environment entry>" and "env-entry-value=<value of environment entry>". The target needs additional resources (DTDs, schemas and "assembly-utils.xml") which must be provided in a directory specified with property "resource-dir=<directory>".
File assembly-resources/assembly-helpers.xml
in the workflow engine EJB JAR uses the general purposes targets
described above and adds to them, thus providing specific targets
for the workflow engine EJBs.
adapt-wfmopen-modules
Modify the deployment descriptors of WfMOpen modules "de.danet.an.wfcore-ejbs.jar", "de.danet.an.wfcore-callback-ejbs.jar", "de.danet.an.wfcore-client.jar" and "de.danet.an.workflow.wfxml.war". Must be called with properties "src-dir=<directory with distributed modules>", "target-dir=<directory for adapted modules>" and "props=<filename with properties>". The target needs additional resources (DTDs, schemas and "assembly-utils.xml") which must be provided in a directory specified with property "resource-dir=<directory>". An optional property "libs-to-remove" may be set to a comma separated list of files to remove from WEB-INF/lib of the WARs (because they will be supplied by the containing EAR).
prepare-wfmopen-callback-module
Modify the deployment descriptors of WfMOpen module "de.danet.an.wfcore-callback-ejbs.jar". Must be called with properties "src-dir=<directory with distributed modules>", "target-ejb-jar=<name of adapted ejb-jar>" and "props=<properties file>". These properties are the same properties as used for "adapt-wfmopen-modules". In addition, they must include a value for the key "@@@_JNDI_Callback_Name_Prefix_@@@" used to derive the global JNDI name of the callback EJBs. These must, of course, be unique for every deployment of the callback EJBs. (Note that you can use the property "token-replacements=<properties file> to simply "add" this property to the general WfMOpen properties file, see general helper "adapt-ejb-jar".) Property "handler" specifies which tool agent invocations are handled by the adapted module, i.e. its value must correspond to the value used for the "Handler" attribute of the application definition in the process definition. The target needs additional resources (DTDs, schemas and "assembly-utils.xml") which must be provided in a directory specified with property "resource-dir=<directory>".
adapt-client-jar
This target is called by "adapt-wfmopen-modules". It configures the StandardWorkflowEngineFactory by adding a file de.danet.an.workflow-wfs.properties with an appropriate entry to the client jar. Must be called with properties "src-client-jar=<filename of distributed client jar>", "target-client-jar=<filename of adapted client jar>" and "props=<filename with properties>".
make-deployment-service
Replace strings with other strings in a deployment descriptor as specified by a properties file and wraps the result as a SAR. This target is provided because JBoss documentation does not explicitly state that you can put arbitrary deployment descriptors (e.g. for creating a data source) in an EAR. You can, however, wrap them in a SAR and put this SAR in the EAR (and have it deployed by an entry in "jboss-app.xml". This target must be called with properties "deployment-xml=<the deployment description>", "dest-file=<filename of the SAR>" and "props=<filename with properties>".
File assembly-resources/assembly-helpers.xml
in the utility EJB JAR uses the general purposes targets
described above and adds to them, thus providing specific targets
for the utility EJBs.
adapt-util-ejbs
Modify the deployment descriptors of utility ejbs by replacing given strings with other strings as specified in a properties file and adding security information retrieved from the same properties file. Must be called with properties "src-ejb-jar=<filename of distributed ejb jar>", "target-ejb-jar=<filename of adapted ejb jar>" and "props=<filename with properties>". The target needs additional resources (DTDs, schemas and "assembly-utils.xml") which must be provided in a directory specified with property "resource-dir=<directory>".
adapt-util-modules
Modify the deployment descriptors of the utility library modules. Must be called with properties "src-dir=<directory with distributed modules>", "target-dir=<directory for adapted modules>" and "props=<filename with properties>". The target needs additional resources (DTDs, schemas and "assembly-utils.xml") which must be provided in a directory specified with property "resource-dir=<directory>".
A sample properties file for use with the above ant scripts is shown below.
# # Information needed for
application assembly #
# Adapt utility EJBs' JNDI names. They have no "reasonable" defaults,
# so we have to specify very much. Note that these JNDI names are
# define separately as the utility EJBs may be shared between
# different applications. Note that "ejb/" will be prepended to the names
# specified below automatically and the entries for local home interfaces
# have "Local" appended to the name.
@@@_Utility-EJBs_UtilEJB_JNDI_Name_@@@ = \
de.danet.an.wfdemo.util-lib.Util
@@@_Utility-EJBs_KeyGenEJB_JNDI_Name_@@@ = \
de.danet.an.wfdemo.util-lib.KeyGen
@@@_Utility-EJBs_KeyGenLockEJB_JNDI_Name_@@@ = \
de.danet.an.wfdemo.util-lib.KeyGenLock
@@@_Utility-EJBs_EJBSinkEJB_JNDI_Name_@@@ = \
de.danet.an.wfdemo.util-lib.EJBSink
# Adapt utility EJB's data source reference
java\:/DefaultDS = java:/WfMOpenDS
# Adapt other EJBs' JNDI names. Most application servers require that
# you specify JNDI names although all references to the EJB are via
# links within the application. We simply define a prefix for those.
# This prefix is also used for JNDI names of other resources. Note that
# "ejb/" will be prepended to the prefix specified below when used to
# derive JNDI names for EJBs.
@@@_JNDI_Name_Prefix_@@@ = de.danet.an.wfdemo.
util-ejbs-security-domain = java:/jaas/wfdemo
util-ejbs-security-roles = \
WfMOpenAdmin: \
KeyGen*KeyGenLock*EJBSink*Util;
util-ejbs-security-identities = TimeoutHandler:WfMOpenAdmin
util-ejbs-security-principals = TimeoutHandler:WfMOpenAdmin_Principal
# Adapt workflow engine (note that the engine uses the util EJBs,
# necessary replacements are already covered by the properties above).
java\:/jaas/wfmopen = java:/jaas/wfdemo
The workflow EJBs can be deployed in the usual way defined by J2EE:
<application>
<display-name>My application using WfMOpen</display-name>
<module>
<ejb>de.danet.an.util-ejbs.jar</ejb>
</module>
<module>
<ejb>de.danet.an.wfcore-ejbs.jar</ejb>
</module>
<module>
<ejb>some.user.my.application.jar</ejb>
</module>
</application>
Make sure that you have included all libraries needed by the
workflow EJBs in the lib/
directory of your J2EE application as described in Section 1.3.4, “Workflow module”. This is a usable configuration
if you only define workflow processes without any resources
(i.e. only automatically executed activities). If resource
assignment to activities is needed, some additional services
have to be supplied as described below.
If you combine the workflow engine EJBs and servlets (packed as
WARs) in a single EAR, it is advisable to have libraries used by
both components only in the EAR (i.e. not in the WARs'
WEB-INF/lib directory. In such a
configuration, the libraries must explicitly be deployed as Java
modules in application.xml. Note that this
and other packaging aspects are not WfMOpen specific. Rather
they apply to J2EE applications in general and details are
bexond the scope of this manual. See one of the many books about
J2EE for further informations.
An issue not necessarily handled by a workflow core service is
the issue of resource assignment. The OMG specification
explicitly leaves this topic to a to-be-defined resource
assignment facility. We have therefore chosen to introduce a
simple interface to a resource assignment service in our
design. This interface is described in detail in the package
de.danet.an.workflow.spis.ras.
In order to keep this interface easily implementable by any kind of architecture, access to this service is not based on JNDI and an EJB home interface. Access rather follows the established generic pattern to create a service using a factory class. In order to use the workflow component, an implementation of this service must be provided.
The workflow component includes a sample implementation of a resource assignment service. If you want to use this implementation, some additional configuration issues arise which are discussed in Section 6.1, “The sample assignment service”.
The callback module should be adapted by using the target
"prepare-wfmopen-callback-module" as described in Section 1.4.1.2, “Helpers for adapting the workflow engine EJBs”. This
requires basically the same properties as adapting the core
modules, i.e. a basic knowledge about the workflow engine
configuration. In order to distinguish the callback EJBs from
the ones used in the engine core and in other callback module
configurations, each deployment must specify an individual
additional property
@@@_JNDI_Callback_Name_Prefix_@@@. This is
used to derive the global JNDI name of the callback EJBs. To
avoid a complete properties file for every callback module
adaption, this property may be put in its own properties
file. This properties file is then passed to the invocation of
the ant target as property
token-replacements. "Token-replacements" is a
mechanism supported by the ant helpers that allows to override
(and therefore also add) individual properties in the general
properties file.
Also required is the specification which tool agent invocations
are to be handled by the callback module. This is determined by
the ant property handler. Its value must
correspond with the value of the attribute
Handler used for the application declaration
in the process definition (see Section 4.2.5, “Defined extensions”).
[1] Most applications servers still support distributed transactions if one participating resource does not support distributed transactions. If your application server does, you may use a database that does not support distributed transactions. Be prepared to get some warnings from your application server, though.
[2] The provided RDBMS specific scripts were generated by processing this file with the DDLUtils for the specific RDBMSs.
[3] You should expect that only EJBs that are to be looked up by clients require binding to global JNDI names. It has turned out, however, that some application servers require explicit specification of global JNDI names for all EJBs, and others (even worse) choose default global JNDI names based on the EJB's names. Therefore, to avoid conflicts between different instances of the workflow engine on one application server, global JNDI names must be supplied in any case.
[4] The other supported methods also have some benefits; it depends on your usage scenario.
[5] Thus you have three possibilities to provide the required priviledges:
In the user management system used by your application server, make all users of the workflow engine members of the role "WfMOpenAdmin".
If your application server supports mapping between application roles and roles managed in your security domain (JBoss does not support this, e.g. Sun AS does) you can map "WfMOpenAdmin" to an existing role in your security domain, thus allowing all users in the existing role to access the workflow engine.
In all deployment descriptors, replace "WfMOpenAdmin" with the name of an exsting role in your user management system. This is typically done during deployment but may also be done during application assembly.
[6] The source distribution includes a stylesheet that, together with the appropriate invocations from ant scripts, adds security information to deployment descriptors.
[7] If
you use JBoss, you do not have to set the endorsed library
directory, because JBoss comes updated libraries in its
$JBOSS_HOME/lib/endorsed directory. This
directory is automatically set as endorsed directory in the
JBoss run-scripts.
Table of Contents
Both WfProcess and WfActivity
objects can assume the same six different states. The following table
itemizes these states and explains their meaning for processes and
activities.
Table 2.1. Meaning of execution object states
| state \ object | process | activity |
|---|---|---|
open.not_running.not_started | After creation the process is active and ready to be initialized and started. | After creation the activity is active and ready to be initialized and started when its start condition is fulfilled. |
open.running | The process is active and executing in the workflow. The process may start new activities. | The activity is executing in the workflow. The activity is invoking the implementing tools or a sub process was started and is running. |
open.not_running.suspended | The process is active and quiescent, but ready to execute. Its execution is temporarily paused, so that no further activities depending on this process may be started. | The execution of the activity is temporarily paused. If the activity is implemented as a sub process the process is also suspended. |
closed.aborted | Indicates that the enactment of the process has been aborted before normal completion. The only assumption on the state of activities depending on this process is that no activity is running. Note, however, that tools may still be running if they do not support asynchronous termination. | Indicates that the enactment of the activity has been aborted before normal completion. No assumptions on the state of sub processes and tools depending on this activity are made when it enters this state. |
closed.terminated | Indicates that enactment of the process was stopped before normal completion. It is assumed that all activities depending on this process have never been started or are completed or are terminated when it enters this state. | Indicates that enactment of the activity was stopped before normal completion. It is assumed that all sub processes and tools depending on this activity are either completed or are terminated when it enters this state. |
closed.completed | When a process has finished its task normally in the overall workflow process it enters the completed state. It is assumed that all activities associated with the process are completed or not started when it enters this state. Further, the combination of the conditions on the incoming transitions of activities that are not started must evaluate to false. | When an activity has finished its task normally it enters the completed state. It is assumed that all tools or sub processes associated with the activity are completed when it enters this state. |
During the life cycle of processes and activities their states change.
The following figure shows supported state transitions of
WfProcess and
WfActivity objects.
As can be seen in the figure, both the
WfProcess and
WfActivity objects start in state
open.not_running.not_started when they are
created and finish in one of three different closed states.
State transitions are triggered by the client API and the engine or can be an reaction to exceptions occuring when invoking tools.
The following table shows how calling a client API operation changes the state of an execution object (process or activity). The numbers used in the following tables refer to the state transitions in the above state diagram.
Note that triggering a state change will cause the workflow engine to either make the intended transition or to throw one of the exceptions declared in the API (see Section A.1.36, “Interface WfExecutionObject”, Section A.1.42, “Interface WfProcess” and Section A.1.29, “Interface WfActivity”). As a result of the transition made, however, the object's state may further be updated by the engine or other clients running in different threads. Thus querying the state of an execution object immediately after successfully triggering a state change may return a state different from the target state of the transition in the table.
Table 2.2. State transitions triggered by client API calls
| object \ method | start | suspend | resume | terminate | abort | complete |
|---|---|---|---|---|---|---|
| WfProcess | 1 | 4 | 3 | 2, 7 | 5 | n. a. |
| WfActivity | n. a. | 4 | 3 | 2, 7 | 5 | 8, 9 |
The "unobservable" (from the client's point of view) state
transitions caused by a call to complete
may seem strange at first. See the method's API documentation
(complete())
for further information about the behaviour.
Usually, state transitions of an execution object will cause further state transitions of other execution objects. There are six cases to distinguish, which are shown in the following table. The head row of the table defines the state transition of the triggering object. This transition may influence the triggered object (triggering object -> triggered object). Its potential transitions are listed in the table elements. E. g. table element (1(a)) in the second table row (WfProcess (parent) -> WfActivity) and fifth column (3) means: The state transition 3 of a parent process may cause a state transition 1 of its activities if the start condition of the activities is fulfilled.
Special attention has to be paid to state transitions of
activities with manual start and/or finish mode. These modes are
implemented by setting the activity object to state
open.not_running.suspended instead of state
open.running (manual start mode) or state
closed.completed (manual finish mode). When
resuming an activity object (transition 3) the engine will
therefore take into account why the activity was suspended and proceed
accordingly.
Table 2.3. State transitions triggered by the engine
| object \ transition | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|---|---|---|---|---|---|---|---|---|---|---|
| WfProcess (parent) -> WfActivity | 0 | 1(a) | 1(a) | 5, 7, 4(j) | n. a. | 7 | n. a. | n. a. | ||
| WfProcess (sub) -> WfActivity | n. a. | n. a. | n. a. | 5 | 8 | 7 | n. a. | n. a. | ||
| WfActivity -> WfProcess (parent) | n. a. | n. a. | 4 | 6(d), 7(e) | 7(c) | |||||
| WfActivity -> WfProcess (sub) | 0 & 1(k) | n. a. | 3 | 4 | 5 | n. a. | 7 | n. a. | ||
| WfProcess -> WfProcess (itself) | 5(b) | n. a. | n. a. | |||||||
| WfActivity -> WfActivity (itself) | 4(f) | 4(g), 6(h) | 5(b) | 4(g), 6(i) |
If the start conditions of the activity evaluate to true.
If the triggering transition 4
(to open.not_running.suspended) was caused
by an activity state transition 5 (to
closed.aborted). Occurs if an activity
aborts (causing everything else to abort) and the process (or an
activity of the process) is in state
open.running. Then
closed.aborted can only be reached via an
intermediate
open.not_running.suspended.
If there are no more running activities or activities with start conditions evaluating to true.
If there are no more running activities and no
activities with start conditions evaluating to true and all
closed activities have state
closed.completed.
If there are no more running activities and no
activities with start conditions evaluating to true and one or
more closed activities have a state other than
closed.completed.
If start mode is manual.
If the activity's finish mode is manual and no work remains to be done.
If activity was suspended because finish mode is manual.
If the activity's finish mode is automatic and no work remains to be done.
If the activity cannot be terminated.
If the start mode of the activity is manual, creation and start of the sub-process will be delayed until the activity has been resumed.
Besides the triggering by the client or the engine, there are three more possible causes for state transitions:
A failure to invoke a tool causes state transition 7 of the
invoking WfActivity object.
The detection of a loop causes the activities on the path to
be reset, i.e. their state changes internally from
closed... to
open.not_running.not_started (see Section 4.3.4, “Loops” for details about loops). This change of
state is not recorded as an audit event, because the
repeated execution of an activity is interpreted as several
instances of the activity being executed one after the
other. Thus the first activity instance is started, runs and
completes, then the second activity instance is started,
runs and completes. There is no observable change from
closed... to
open.not_running.not_started.
If the preliminary choice of an activity in a deferred
choice is revoked (because another activity is chosen), its
state changes from open.running to
open.not_running.not_started (see Section 4.3.5, “Deferred choice” for details about the deferred
choice). This change of state is recorded as an audit event,
as it is part of the activity's execution sequence.
Besides events triggered by a client, an activity may also receive exceptions. Exceptions are defined in the XPDL specification as a general mechanism to signal an exceptional condition to an activity. The only specifically defined exceptions are those generated by the arrival of a deadline that has been defined for an activity. WfMOpen additionally supports handling exceptions from tool invocations, see Section 3.5.4, “Exception handling” for details.
As far as state is concerned, exceptions are basically handled like the final complete call[8]. Any running tool is terminated and tools not yet invoked are skipped.
It may at first be surprising that the activity reaches
closed.completed when an exception
occurs. However, any other resulting state of an activity would
have a strange effect on the final process state, as it would
prohibit the process from reaching the completed state (see Section 2.1, “States of processes and activities”)[9]. From a
process' point of view everything is all right. A deadline may
have occurred and some special transitions may have been taken,
but the process has still performed within its specification.
Things look a bit different, though, from the perspective of a subprocess started by an activity that receives an exception. This process is forcefully terminated by its requester (the activity that has received the exception). It therefore assumes the state terminated or aborted. In contrary to the normal state transitions, this does not cause the requesting activity to assume the same state as the activity is set to state completed by the exception processing.
Under normal circumstances, the occurrence of an exception should
be derived from the transitions taken in a process. However, as a
help for automated evaluations, WfMOpen has introduced the
sub-states closed.completed.normal and
closed.completed.abandoned with the latter
being assigned to an activity that has been completed due to an
exception.
XPDL introduces deadlines, OMG knows about a "suspended" state, but neither knows about the other. This leaves the question of how the suspended state affects deadlines. We have defined the semantics as follows.
If an activity is set to state suspended, deadlines are suspended as well, i.e. no exceptions from deadlines will occur[10]. Note that "if an activity is set to state suspended" is not the same as "if an activity is in state suspended". Activities may also reach the state suspended if they have manual start or finish mode. In these cases deadlines are not suspended[11].
If the deadline has been defined as an absolute date time value (see Section 4.2.4, “Deadlines” then setting an activity in the suspended state will not prolong the deadline. If the deadline is reached while the activity is suspended, the related exception will be delivered immediately when the activity is resumed.
If the deadline has been defined as a duration then setting an activity in the suspended state will prolong the deadline, i.e. the deadline will be delayed by the accumulated time that the activity has spent in the suspended state.
Dynamic deadline conditions, i.e. conditions that depend on process relevant data, will be re-evaluated every time the activity is resumed. The advantage of this behavior is that it effectively offers you a choice. If you want your expiration date to remain, you simply use only process relevant data that does not change. The disadvantage is that in order to have invariant process relevant data, you may have to make copies of several items (or, maybe better, calculate your deadline in an independent expression and keep it in some data field).
Maybe the biggest trap in re-evaluation is that the simple
conversion of a duration to an absolute date "new
Date((new Date()).getTime() + duration)" will not
work. While this yields a date, which is not prolonged by the
suspend state, it will be re-evaluated when the activity is
resumed. Thus the deadline will probably be delayed even more than
by using the duration in the first place. There is no solution to
this other than saving the start time of the activity in a data
item (e.g. by calling the JavaScript tool as first tool of the
activity).
Workflows may be run in debugging mode. In this mode, the activities assume some additional, intermediate states. Note that the associated state transitions are neither recorded nor distributed as state change events. The debug mode has been designed to run the workflow in a way that resembles the normal execution as closely as possible. The debug mode is not a simulation. It can best be compared to running a program in a debugger, i.e. the workflow is really executed. There are, however, predefined break points and the invocation of tools may be simulated instead of actually performed.
Debugging mode is enabled for a specific process by calling
setDebugEnabled(true) on the
process after creating, but before starting the process (see
setDebugEnabled(boolean)).
Debugging can also be enabled for a process type by default using the XPDL extension mechanism as described in Section 4.2.5.2, “Extensions on Package and Process Level”.
When debug mode is enabled, the execution of activities breaks before the invocation of a tool and before completion of an activity.
Immediately before invoking a tool, the activity's state changes
to open.running.debug.invoking. To continue
the execution, the activity's state must be changed to either
open.running or to
open.running.debug.skipping. In the former
case, the tool will be invoked as in non-debugging mode. In the
latter case, tool invocation will be skipped and the activity
will either assume the state
open.running.debug.invoking again (if there
are more tools to be executed by the activity) or the state
open.running.debug.completing (if the
invocation of the last tools has been skipped, see below). Of
course, the process data must subsequently be modified manually
to reflect the changes that would have been made by the tool
invocation.
Before the activity is eventually closed, it enters one of the
states open.running.debug.terminating,
...aborting or
...completing depending on the closed-state
that the activity will assume. To continue execution and cause
the activity to assume it proper closed state, the activity's
state must be changed to open.running.
In debugging mode, exceptions thrown by tools (i.e. calls to
abandon, see abandon(java.lang.String)
will cause the activity to assume the state
open.running.debug.abandoning. To continue
the execution, it is not sufficient to provide the possibility
to change the state to open.running as
described above for the "normal" transitions to the closed
state. There may be several exceptional transitions defined, and
it must be possible to specify which exception should be used,
else it wouldn't be possible to test the different paths during
debugging.
In order to avoid polluting the interface with methods that are
only used for debugging, we have defined a special sequence of
method invocations that cause the execution to continue
(i.e. the state will change to
closed.completed.abandoned and the
execution of subsequent activities will be triggered as
specified by the transitions). You first change the state to
open.running.debug.awaiting_exception and
then call abandon (see abandon(java.lang.String))
with the name of the exception to be processed. The preceding
state change causes abandon(String) to
behave differently from normal operation, effectively continuing
execution as described above.
In order to avoid any ambiguities, we strongly recommend to execute the two operations (state change and abandoning) in a single transaction. This may be achieved by using a user transaction as described in the J2EE specification or by using the method invocation batch (see Section A.2.31, “Class MethodInvocationBatch”).
WorkflowService wfs = ...;
MethodInvocationBatch mib = new MethodInvocationBatch(true);
mib.addInvocation (activity, "changeState",
new String[] {"java.lang.String"},
new Object[] {"open.running.debug.awaiting_exception"});
mib.addInvocation (activity, "abandon",
new String[] {"java.lang.String"},
new Object[] {exception});
MethodInvocationBatch.Result mir
= (MethodInvocationBatch.Result)wfs.executeBatch(mib);
Deadlines will be be started in debugging mode just as in
non-debugging mode. However, nothing happens when deadlines are
reached. The state of deadlines may be monitored by calling
deadlines(). To
cause the process to proceed as if a synchronous deadline had
been reached, you must first call
abandon(String), which causes the activity
to assume the state
open.running.debug.abandoning, and then
continue execution as described for exceptions in general above
(see Section 2.6.3, “Effect on exceptions”). This may, of
course, be done before the deadline has been reached,
i.e. the effect of a deadline may be tested without actually
waiting for the associated time (which may be quite long) to
elapse.
In order to simulate an asynchronous deadline, the state of an
activity must first be changed to
open.running.debug.forwarding_exception. This
causes a subsequent call to abandon to
mimic the behavior of an asynchronous deadline,
i.e. transitions will be triggered as specified for the given
exception. The activity will automatically resume the state that
it had before the change to
open.running.debug.forwarding_exception. Of
course, this sequence of method calls should also be executed in
a single transaction, as described above.
[8] The impact on transitions is quite different, of course.
[9] We could have relaxed this dependency, allowing the process to reach the completed state even if an activity is terminated or aborted, provided this state was reached due to an exception. But then the state definition wouldn't be OMG compliant any more.
[10] There has been some disussion if this is the proper behaviour. The reasoning is that setting the activity in the suspend state is nothing that occurs during normal workflow execution. It is a deliberate management action. This action would become farcial if it could be circumvented by a deadline.
[11] We assume that a process designer who defines start or finish mode manual together with a deadline wants that deadline to be executed to e.g. notify the administrator.
Table of Contents
The following figure shows the overall structure of Danet's workflow component.
As can be seen in the figure, the workflow core component provides an EJB based client API. Helper classes on the client side hide most of the EJB invocation details, thus enabling the usage of the component without constantly keeping EJB details in mind.
The workflow component relies on the availability of a resource assignment service. As this service must be provided to the workflow component, it can be thought of as an additional API, or SPI to be precise, of the workflow component.
The distribution includes a sample implementation of such a resource assignment service which is described in detail in Chapter 6, The sample resource assignment service.
Finally the workflow package defines an API (SPI) used to invoke applications that perform activities.
The following sections describe each API in detail.
A standard workflow Java API has not been defined yet. Still, we did not want to provide users of our workflow component with a completely proprietary API. Therefore, we have taken a two stage approach.
As a first step, we have adapted the API specified by OMG's
Workflow Management Facility
Specification, V1.2 to the Java domain. The result
of this adaptation can be found in the package description of
de.danet.an.workflow.omgcore (see de.danet.an.workflow.omgcore or JavaDoc).
The package defines the core workflow classes such as
WfProcess,
WfActivity etc. A detailed description of
the process used to derive the Java interfaces from the OMG
specification can be found in the package description.
The OMG core workflow interfaces define a workflow model as shown in the following diagram.
The central classes of the model are
WfProcess (see Section A.1.42, “Interface WfProcess”) and
its constituting WfActivity instances
(see Section A.1.29, “Interface WfActivity”). Processes
of the same type can be created and accessed with their
WfProcessMgr (see Section A.1.43, “Interface WfProcessMgr”).
Examining the OMG interface closely, we found that it lacks some functions that we would like to offer. For some OMG interfaces we have in a second step therefore defined a corresponding interface that extends the OMG base interface.
We have also added some interfaces for areas that the OMG specification has purposely omitted from its scope (e.g. access to process definitions).
The starting point for using the workflow engine is the
WorkflowServiceFactory. Use this class
to create a new WorkflowService (see
Section A.2.52, “Class WorkflowServiceFactory”,
especially setProperty(java.lang.String, java.lang.Object),
and Section A.2.51, “Interface WorkflowService”). The
workflow service provides the methods to access the process
definitions, processes etc.
Note that the extended API has been defined completely independent of J2EE. It is possible to implement this API with POJOs, though it may turn out to be difficult to provide remote access, reliable transactional behavior, security and scalability without using J2EE.
The implementation of the API provided by WfMOpen is J2EE based because we found this middleware an ideal basis for a workflow engine that can meet the demands of enterprises. The workflow service factory implementation provided by WfMOpen is described in de.danet.an.workflow.ejbs.client.StandardWorkflowServiceFactory. See this description for more information about required configuration parameters.
This section covers a step-by-step description of the process of building a basic sample client.
The example helps you to learn how to set up your compilation and runtime environment and finally, you will be able to retrieve some information from the workflow engine.
Let's start with a first look at the code we need for this purpose:
package samples;
import java.util.Iterator;
import java.rmi.RemoteException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import de.danet.an.workflow.api.WorkflowServiceFactory;
// Section A.2.52, “Class WorkflowServiceFactory”
import de.danet.an.workflow.api.WorkflowService;
// Section A.2.51, “Interface WorkflowService”
import de.danet.an.workflow.api.ProcessDirectory;
// Section A.2.44, “Interface ProcessDirectory”
import de.danet.an.workflow.omgcore.WfProcess;
// Section A.1.42, “Interface WfProcess”
import ProjectLoginContext; // Section 3.3.2, “Gaining access”
/**
* A sample workflow client.
*/
public class TestClient {
private static LoginContext lctx = null;
/**
* Main method called when started from shell.
* @param args arguments
*/
public static void main(String args[]) {
System.out.println("Started");
// This block authenticates a user. It is needed only once
// within a client program (see Section 3.3.2, “Gaining access”).
try { // ❶
lctx = new ProjectLoginContext();
lctx.login();
} catch (LoginException exc) {
System.err.println("Login failed: " + exc.getMessage());
System.exit(-1);
}
// Here starts the real work.
WorkflowService wfs // ❷
= WorkflowServiceFactory.newInstance().newWorkflowService();
try {
ProcessDirectory dir = wfs.processDirectory(); // ❸
Iterator procs = dir.processes().iterator(); // ❹
while (procs.hasNext()) {
System.out.println
("Proc: " + ((WfProcess)procs.next()).name()); // ❺
}
} catch(RemoteException exc) {
System.err.println
("Process directory not accessible: " + exc.getMessage());
System.exit(-1);
}
}
}| ❶ | The purpose of this block will be explained below (see Section 3.3.2, “Gaining access”). It has nothing to do with the genuine workflow engine functionality. |
| ❷ |
The first step in using the workflow service is to obtain a
reference to a |
| ❸ |
From the workflow service we can get the
|
| ❹ |
We call |
| ❺ | For this example we simply output the names of the processes (see name()). Of course, you may add print statements for additional attributes. |
First of all, you have to install the database (see Section 1.2, “Preparing the database”) and deploy the workflow ejbs (see Section 1.4, “Deploying the component”).
If you have installed a demo application (see Appendix C, The demo applications) you can use it as the server for the sample client.
Next, add the following libraries to your compilation classpath:
Danet's wfcore API library
(de.danet.an.wfcore-apis.jar)
Danet's AN utility library (de.danet.an.util.jar)
All libraries needed by your J2EE client environment
All libraries needed by your EJB client environment
All third party libraries referenced in Section 1.3.7, “Additional libraries”
You should now be able to compile the sample client code.
After the successful compilation of your client, you need to add the following items to your runtime classpath:
All libraries from the compilation classpath.
Danet's wfcore client library
(de.danet.an.wfcore-client.jar), adapted to your
server configuration as described in
Section 1.3.4, “Workflow module”[12]
The directory with the preferred Log4J configuration for
your client (in a file named
log4j-appl.xml).
The log4j library.
If you now try to start the sample client, you will get an error message, stating that the environment is unable to locate a login configuration. This is due to the fact that every access to an EJB is security controlled by the application container.
Access to EJBs may be secured by specifying roles that have
access to methods. In the sample application, a single security
role named WfMOpenAdmin has been
configured, which a user has to adopt in order to gain full
access to all application components (see the
ejb-jar.xml in the
de.danet.an.wfcore-ejbs.jar).
Since the J2EE specification does not define how to associate roles with a client, things get a bit vendor-specific here. Lookup your J2EE server's documentation to find out how things are handled in your environment. A popular method used by several J2EE vendors is to use JAAS based authentication. We'll explain the mechanism using the JBoss application server as an example.
Roughly, JAAS is based on a session related
LoginContext that holds
security information (including associated roles) about a
Principal (typically a user's
login name). One or more configurable "login modules" provide
this information. The login modules are invoked when
LoginContext.login() is called
(see ❶). The login
modules may use a callback to query credentials. If proper
credentials are supplied, the login module adds information
(such as roles) to the
LoginContext.
If you have no predefined callback implementations available, you may use this example:
import java.io.IOException;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.TextOutputCallback;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import javax.security.auth.login.FailedLoginException;
/**
* Simple login context for unit tests.
*/
public class ProjectLoginContext extends LoginContext {
public final static String USERNAME = "junit";
private static class CBH implements CallbackHandler {
public void handle (Callback[] callbacks) ❶
throws UnsupportedCallbackException, IOException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof TextOutputCallback) { ❷
// display the message according to the specified type
TextOutputCallback toc = (TextOutputCallback)callbacks[i];
switch (toc.getMessageType()) {
case TextOutputCallback.INFORMATION:
System.err.println(toc.getMessage());
break;
case TextOutputCallback.ERROR:
System.err.println("ERROR: " + toc.getMessage());
break;
case TextOutputCallback.WARNING:
System.err.println("WARNING: " + toc.getMessage());
break;
default:
throw new IOException("Unsupported message type: " +
toc.getMessageType());
}
} else if (callbacks[i] instanceof NameCallback) { ❸
// prompt the user for a username
NameCallback nc = (NameCallback)callbacks[i];
nc.setName(USERNAME);
} else if (callbacks[i] instanceof PasswordCallback) { ❹
// prompt the user for sensitive information
PasswordCallback pc = (PasswordCallback)callbacks[i];
pc.setPassword(USERNAME.toCharArray());
} else {
throw new UnsupportedCallbackException
(callbacks[i], "Unrecognized Callback");
}
}
}
}
public ProjectLoginContext () throws LoginException {
super ("danetworkflow", new CBH()); ❺
}
}| ❶ |
At the first glance, things look much more complicated than
they are. All we really have to do is implement the call
back handler. It has a single method
|
| ❷ |
A |
| ❸ | This callback is sent if the login module wants a user name. We used a fixed name here and simply set this as the callback result. |
| ❹ | This callback is sent if the login module wants a user credential (which need not be a string, hence it is typed as byte array). We used a fixed password (the name) here and simply set this (converted to a byte array) as the callback result. |
| ❺ |
All we have to do in order to customize the standard
|
The security configuration name used by the
LoginContext must match an entry in the
file that declares all security domains for JAAS. For our client
(and JBoss) we need an entry like this:
danetworkflow {
org.jboss.security.ClientLoginModule required;
};
This declares that a single login module
org.jboss.security.ClientLoginModule
should be called.
Finally we must tell JAAS that it should use our
configuration file by starting the java virtual machine with this
additional parameter: -Djava.security.auth.login.config=auth.conf.
The login context in our example provides credentials for the
user “junit”. So we have to make sure, that the
user “junit” is able to adopt the role
StaffManagementRole_0. The described
JBoss security configuration verifies given
credentials on the basis of the Jetspeed2 user management
component. Thus, to gain
the proper access rights, make sure that a user name
“junit” is defined within the Jetspeed2 portal and
that this user is part of the administrator group (the group
with the id “0”).
With these security settings, the client should now display a list with all processes currently running (or closed but not deleted) in the workflow engine.
The resource assignment SPI is described in detail in section de.danet.an.workflow.spis.ras. It makes the resource assignment service a pluggable component, i.e. you are free to choose an assignment service that suits the needs of your business processes and your organization.
The sample resource assignment service included in the WfMOpen distribution (see Chapter 6, The sample resource assignment service) simply supports the selection of specific humans, groups or resources. You may replace this with a component that takes in consideration skills, shift times etc.
A resource assignment service must implement a resource assignment
factory and a resource assignment service as defined in Section A.4.6, “Class ResourceAssignmentServiceFactory”
and Section A.4.5, “Interface ResourceAssignmentService”. An
implementation of ResourceAssignmentFactory
may require additional configuration properties to adapt the
service instances that it creates to the specific
environment. Usually, these properties are retrieved from JNDI
environment entries or from a Java properties file (see Chapter 6, The sample resource assignment service for an example).
The WfMOpen implementation guarantees that the resource assignment
service factory is only used in the context of the
WorkflowEngineEJB. Therefore, if you use JNDI
environment entries to configure your factory, it is sufficient to
add those entries to the
WorkflowEngineEJB. Note that the guarantee to
use the resource assignment service factory in this context only
is implementation specific. Therefore the general SPI description
leaves the issue of which EJBs require the entries deliberately
open.
The tool invocation SPI provides the possibility to add
"tool-plugins" to the workflow engine. Implementing tools is quite
easy. The only interface that a class must implement in order to
be usable as a tool is ToolAgent (see Section A.3.10, “Interface ToolAgent”).
The tools that are bundled in the WfMOpen distribution are described in Chapter 5, Tools. Their sources should should be consulted as examples for tool agent implementation.
As explained in the package description of the application
invocation interface (see de.danet.an.workflow.spis.aii), tool agent
invocations are conceptually asynchronous, i.e. the workflow
engine does not expect the invoke method to
return a value. This is a necessity for supporting tools that run
for a long period of time (e.g. a tool that allows manual input of
data). The process that calls complete on the
activity may be completely different from the thread that invoked
the tool agent.
Practical experience shows, however, that a lot of tools can
reasonably execute completely within the invoke method. In order
to simplify the implementation of this class of tools and avoid
some problems with transactions (again, see de.danet.an.workflow.spis.aii for details),
the interface ResultProvider (see Section A.3.8, “Interface ResultProvider”)
has been defined. A tool agent implementing this interface can
provide its result in a simple function call and the workflow
engine handles forwarding the result to the activity and
completing the activity.
Sometimes, tool agents need access to some workflow engine
functions. While it is technically possible for tool agents to
access the WorkflowEngineEJB (and older
versions of the tools coming with WfMOpen did rely on this), this
behavior is strongly discouraged. The methods that may be called
by tool agents are made available in a
ToolAgentContext (see Section A.3.11, “Interface ToolAgentContext”). Tool
agents that want to use this context must implement the interface
ContextRequester (see Section A.3.4, “Interface ContextRequester”)
and will receive the context before method
invoke is called[13].
As tool agents run in the application server context, they can
always access the application server's JNDI directory using
"new InitialContext()". This
context provides all global entries (including those restricted
to local access from within the JVM,
i.e. "java:...").
Sometimes it may be desirable to use logical names as provided
for EJBs ("java:comp/env/...") instead of
global names. This may facilitate deployment, because the
mapping of the logical names used by the tool agents to global
names can be administered in the same way as e.g. for mapping
data sources used by EJBs.
While tool agents are not EJBs themselves, WfMOpen guarantees
that tool agents run in the context of a business method of the
InvocationHelperEJB. Tool agents
can therefore additionally lookup via JNDI all entries that are
bound to the "java:comp/env/" namespace of
the InvocationHelperEJB. To
provide a logical name for use by a tool agent, it is therefore
sufficient to add the required entry to the
InvocationHelperEJB's section in
ejb-jar.xml. We recommend to put entries
created in this namespace for the sole use of a tool agent in a
subcontext
"java:comp/env/toolagents/".
agent
name/...
As can be seen in the declaration of the
ToolAgent interface (see Section A.3.10, “Interface ToolAgent”),
tool agents can throw RemoteExceptions
and CannotExecuteExceptions.
In general, and especially in the J2EE environment,
RemoteExceptions received when
accessing a (remote) component can be interpreted as an
indication that a service is temporarily unavailable. The
current transaction should be rolled back and retried. To
avoid having to implement this behaviour in every tool agent,
the tool agent may indicate such a condition by raising a
RemoteException. Usually, the tool
agent does not create such an exception itself, rather it
propagates an exception that it has received when accessing a
remote component. The workflow engine does roll-back and
re-invocation automatically if a
ToolAgent raises a
RemoteException.
Tools may also throw
CannotExecuteExceptions during their
execution. The workflow engine's default response to such an
exception is to terminate the activity, and thus the process
(see Section 2.1, “States of processes and activities”). An exception raised by a tool
is considered an indication of unexpected behaviour and it
would be dangerous to continue the process after encountering
an unexpected behaviour of a tool.
The default behaviour may be overridden by either the tool or
the application declaration. A tool can specify a mapping of
Java exceptions that are reported as cause of the
CannotExecuteException to process level
exceptions (see Section 2.4, “Exceptions”) by
implementing the interface
ExceptionMappingProvider (see Section A.3.5, “Interface ExceptionMappingProvider”).
The process definition can define such a mapping as described
in Section 4.2.5.1, “Extentions of Application Declaration”. Exceptions reported as
cause of the CannotExecuteException by
the tool are first matched against the mappings from the
application definition and then against the mappings from the
tool.
Note that there is some redundancy between exception mapping
and the method abandonActivity made
available by the workflow engine context (see Section 3.5.2, “Accessing the workflow engine context” and Section A.3.11, “Interface ToolAgentContext”).
The main difference is that a call to
abandonActivity cannot be redefined by
the application declaration, it will always lead to the
specified process level exception. Method
abandonActivity should therefore be used
if raising a specific process level exception is part of the
tool's bahavioral specification and handling the condition
differently is not an option.
If a tool deliberately uses an exception type as cause when
constructing a CannotExecuteException
and at the same time defines a mapping for this type of
exception, it offers the user the possibility to redefine the
bahavior. This is especially useful if the Java exception type
has subclasses. In this case, the user of the tool has the
possibility to specify special process level exceptions for
the subclasses of the Java exception in the application
declaration and can thus achieve differentiated behaviour.
In addition to defining system exceptions for Java exceptions,
the exception mapping may specify that the invoking activity
should enter the
open.not_running.suspended.abandoning
state when the exception occurs. This will delay the actual
delivery of the exception until the activity is resumed. Such
a behaviour may be desired if unexpected exceptions should
stop the process rather then terminate it. If e.g. combined
with an exception transition that simply leads back to the
activity, this offers the possibility to repeat the tool
(agent) invocation after fixing the exception's cause (e.g. by
modifying some data or restarting a required service).
Instead of simply resuming an activity from state
open.not_running.suspended.abandoning,
the state may first be changed to
open.not_running.suspended.clearing_exception. This
is an intermediate state that causes the activity to clear the
pending exception and immediately proceed to "normal"
suspended state
open.not_running.suspended.suspended. Effectively,
this causes the engine to ignore the exception, i.e. the
engine behaves as if the tool invocation had been successful,
and the activity had been set to the suspended state during
tool invocation using the API[14]. This
feature may be used to manually mend a failed tool invocation
by setting the process data to the state expected after the
(failed) tool invocation and resume the normal workflow.
[12] If you
use the demo application described in
Appendix C, The demo applications you can extract an adapted
client library from the EAR. Go to the directory
$JBOSS_HOME/server/wfdemo/deploy and extract the
file de.danet.an.wfcore-client.jar from
the lib subdirectory in the demo
EAR.
[13] The methods
made available in ToolAgentContext are based
on the experience gained in implementing tools. If you feel that
additional methods should be provided, please let us
know.
[14] Acting as if execution had manually been suspended also applies to deadlines. If deadlines have expired while the activity has been in the suspended state caused by the exception, they will be handled as described in Section 2.5, “Suspended state and deadlines”
As an extension to the OMG API, the WfMOpen workflow engine is capable of managing an unlimited number of process definitions at a time. To gain access to a specific description, a directory component has been established, managing all packages and included process definitions (see Section A.2.43, “Interface ProcessDefinitionDirectory”).
When a new process definition file is imported (via method
importProcessDefinitions), all currently
managed descriptions with the same package id as the imported
package (regardless of the process' name) are removed from the
process definition directory before adding any new process
definition.
Note that replacing a process definition with another version (or removing a process definition) does not affect running processes. Once created, a process remains inseparably associated with the process definition that was effective when the process was created.
The import format for process definitions is XPDL which stands for "XML Process Definition Language". XPDL is a WfMC standard that is currently available as version 1.0 Final Draft.
When using the XPDL and the OMG API together, attention has
to be payed to the usage of some keywords. The most
prominent among those is the usage of the attribute
Id in XPDL vs. the usage of
a key in the OMG API.
Ids are used in the XPDL to
enable references between the different items defined. They
have no significance to the OMG API (with one exception,
see below). The OMG API uses keys to
uniquely identify instances within their context. So an
activity with key "a23" could e.g. be the instance of an
activity that was defined in the XPDL with
Id="do_this".
The one exception where Ids
have significance in our implementation of the OMG API is
the process type. The OMG defines a process manager and this
process manager has a "name" attribute denoting the process
type. Currently, we use the
Id from the XPDL as the
process manager name (this may, however change in future
versions).
It is important to maintain a clean separation between the usage
of Id and
key when programming against the
workflow API. This is sometimes especially difficult,
because keys are often labeled as "ids" in the user interface.
One of the most annoying problems with the current version of
XPDL is the schema defined for InitialValue
and ActualParameter tags. Although XPDL
introduces a SchemaType, initial values and
actual parameters may only be of type string, thus prohibiting
the usage of structured data.
We have therefore defined that the content of the
InitialValue of a
DataField of type
SchemaType is parsed as XML and used to
initialize the data field. The XML may have multiple top nodes,
i.e. a data field may be used to hold "lists"[15]. The XML must be
self-contained, i.e. if you use namespaces they have to be
declared within the string, namespaces of the XML surrounding
InitialValue are not inherited.
Starting with version 1.3.4, WfMOpen supports E4X, the XML
extension for JavaScript. E4X introduces the XML "native" type
(similar to e.g. the JavaScript native "Date" type) and extends
the JavaScript lexical grammer to directly support XML text as
initializers for new objects of this type. With E4X, parsable
XML within JavaScript simply yields a new XML object. Therefore,
no special provisions have to be taken to support actual
parameters of SchemaType. An actual
parameter specified as
<ActualParameter><![CDATA[<Hello/>]]></ActualParameter>
is passed to the JavaScript interpreter like any other actual
parameter expression and evaluates to an XML object that is used
when invoking the tool or sub-process. The XML may also have
multiple top nodes. This can be expressed in E4X as e.g.
<ActualParameter><![CDATA[<><Hello/><World/></>]]></ActualParameter>.
Note that the JavaScript expression need not be literal XML. It
may be an arbitrarily complex JavaScript that ends with an
expression of type XML. The use of complex scripts as actual
parameters is, however, discouraged. A useful alternative to
literal XML is e.g. the selection of a subtree from a process
data item of SchemaType, such as
<ActualParameter>purchaseOrder.item.(id=5)</ActualParameter>.
For backward compatibility with WfMOpen versions prior to 1.3.4,
a special rule applies. If the actual parameter starts with the
string "<j:jelly"[16], it is piped
through the jelly interpreter before being passed to the invoked
tool or sub-process. Within the jelly script, the process
relevant data items are available as variables. These variables
may not be modified (this is similar to the evaluation of an
actual parameter of basic type using JavaScript). Setting a
variable with the same name as a process data item will create a
new variable that hides the process data item.
Besides the jelly core tags, the demo application makes the "xml" and "jsl" tags available by including the respective libraries. We consider these the only useful tags in the context of actual parameter evaluation. However, no special measures have been taken to enforce this subset. If other tag libraries are bundled with the application, these will be available as well. As with JavaScript expression, causing side-effects in actual parameter evaluation is, however, strongly discouraged.
The support for jelly in actual parameter evaluation is deprecated and will be dropped in WfMOpen 2.x.
WfMOpen attempts to parse a DeadlineCondition
using the following methods:
Parse as a duration as defined in the XML Schema Definition (see XML Schema Part 2, "duration").
Parse as a date time specification as defined in the XML Schema Definition (see XML Schema Part 2, "dateTime").
Parse as value/unit pairs. Values can be arbitrary JavaScript expressions, valid unit names are "years", "yrs", "months", "mts", "hours", "hrs", "min" and "sec". There may be only one pair for each unit i.e. "5 years 3 yrs" is illegal.
Value/unit pairs must be separated from each other with at least one whitespace character. Units may follow values immediately if the value is a number, else they must be separated by at least one whitespace.
Any duration unit may be omitted, but the descending order of units must be preserved.
When evaluating the JavaScript expression, process relevant data is available as read-only variables. The evaluation must yield a number.
Parse as a date time specification in the formats "d MMM
yy HH:mm:ss z" and "d MMM yy HH:mm z" (see
java.text.SimpleDateFormat). An
optionally leading "EEE, " (abbreviated day) is
ignored. These formats include RFC822 conformant date time
specifications.
Evaluate as JavaScript. In this evaluation, process relevant data is available as read-only variables. The script must return a JavaScript "Date" type or a number. A result of type "Date" is interpreted as absolute time specification, a number is interpreted as seconds relative to the start time of the activity.
Trying to define a process definition language that can be used for any workflow engine, the WfMC had to leave out some implementation specific details. The missing information has to be provided using vendor specific extentions. The following sections describes the extensions used by WfMOpen.
Within the XPDL file, a tool or application can only be
declared or referenced. XPDL does not specify elements that
can be used to describe the definition of the
application. Usually, the binding to application
implementation is handled for example by an object manager. To
keep the process definition self-contained, we have chosen the
straightforward approach of defining the definition details
within the tool declaration. This has been achieved by
defining an extended attribute named
Implementation.
...
<Application Id="INCREMENT">
<Description>Marking the current station within the transition path.
</Description>
<FormalParameters>
<FormalParameter Id="counter" Mode="INOUT">
<DataType>
<BasicType Type="INTEGER"/>
</DataType>
</FormalParameter>
</FormalParameters>
<ExtendedAttributes>
<ExtendedAttribute Name="Implementation">
<vx:ToolAgent
xmlns:vx="http://www.an.danet.de/2009/XPDL-Extensions1.1"
Class="de.danet.an.workflow.tools.rhino.JSExecutor"
Execution="SYNCHR"
XMLParamterMode="USE_W3C_DOM">
<vx:Property Name="Script"><![CDATA[
java.lang.System.out.println ("Incrementing counter "
+ args["counter"]);
args["counter"] = args["counter"] + 1
]]></vx:Property>
</vx:ToolAgent>
</ExtendedAttribute>
</ExtendedAttributes>
</Application>
In the example above, an application is declared with its
implementation class
(de.danet.an.workflow.tools.rhino.JSExecutor)
specified as an extended attribute. The implementation class
must implement
de.danet.an.workflow.spis.aii.ToolAgent
(see Section A.3.10, “Interface ToolAgent”)
and provide setXXX methods
for each declared Property
element.
In our example
de.danet.an.workflow.tools.rhino.JSExecutor
must thus implement a method
setScript. If the content of a
<Property> node is
text, the required argument of the
setXXX method must be of type
java.lang.String. If the
content of a <Property>
node is another element, the argument may be either
org.jdom.Element or
org.w3c.dom.Element depending
on the tool agent's preferred environment.
The execution type of a tool agent can be defined as
SYNCHR or ASYNCHR
(default) so that it may be executed synchronously or
asynchronously with respect to state evaluation (see Section A.3.10, “Interface ToolAgent”).
The actual parameters passed to the tool that are declared as
<SchemaType> will be
passed as org.w3c.dom.Element
(default), org.jdom.Element
or
de.danet.an.workflow.api.SAXEventBuffer
(see Section A.2.48, “Interface SAXEventBuffer”)
depending on the attribute
XMLParameterMode. Possible values are
"USE_W3C_DOM" (making the default
explicit), "USE_JDOM" or
"USE_SAX". Note that the setting will
only be effective if the tool does not implement the
XMLArgumentTypeProvider
interface (see Section A.3.12, “Interface XMLArgumentTypeProvider”).
An additional attribute Handler (not shown
above) can be used to cause invocation of the tool agent in
another InvocationHelperEJB
than the default one (usually in another EAR). See Section 1.3.5, “The optional callback module” for a general description
of this concept. Note that you must use the extended namespace
http://www.an.danet.de/2009/XPDL-Extensions1.1
instead of the old namespace
http://www.an.danet.de/2002/XPDL-Extensions1.0
if you want to specify the handler.
An
application declaration may optionally include the definition
of mappings of Java exceptions reported by the tool agent to
process level exceptions (see Section 3.5.4, “Exception handling”). The mapping is
declared as child of the ToolAgent
element, before the Property elements:
...
<vx:ToolAgent ... >
<vx:ExceptionMappings>
<vx:ExceptionMapping JavaException="java.lang.Exception"
ProcessException="Error"/>
</vx:ExceptionMappings>
<vx:Property Name="Script"> ...
If the attribute ProcessException is
omitted, the default behaviour of terminating the activity
when the exception occurs is re-established (overriding a
mapping established by the tool agent implementation
programatically, see Section A.3.5, “Interface ExceptionMappingProvider”).
Extensions:
RemoveClosedProcess
determines how the workflow engine removes a closed
process. Values can be
MANUAL,
AUTOMATIC or
COMPLETED
[17]
(default:
AUTOMATIC). Starting
with version WfMOpen version 1.3.1, the value for this
extension may be specified either as attribute
"Value" or as (textual) body of
<ExtendedAttribute>. The
latter form is considered
deprecated. COMPLETED
causes the process to be removed automatically only if
its completion state is
closed.completed. This is useful
for keeping processes that have failed for debugging
purposes.
Debug
if True, the process
will be started in debug mode (see Section 2.6, “Debugging workflows”). This can be specified on
process level only. Starting with version WfMOpen
version 1.3.1, the value for this extension may be
specified either as attribute
"Value" or as (textual) body of
<ExtendedAttribute>. The
latter form is considered deprecated.
AuditEventSelection
The audit events reported by this process will be
restricted as specified in the attribute
"Value". The restriction applies
both to the events reported to an audit handler (see
receiveEvent(de.danet.an.workflow.omgcore.WfAuditEvent))
and the events saved in the audit trail (see history())
(see remarks at the end of this section).
Valid values for the audit event selection are:
AllEvents
All events will be reported. This is the default, i.e. equivalent to not specifying this extended attribute at all.
StateEventsOnly
Only state change events (i.e. events of type
WfStateAuditEvent, see
Section A.1.46, “Interface WfStateAuditEvent”)
will be reported.
ProcessClosedEventsOnly
Only state change events caused by a process assuming the closed state will be reported. This filter is useful if you have clients that use the notification mechanism to wait for the completion of processes.
NoEvents
No events will be reported.
StoreAuditEvents
If the attribute "Value" is set
to "False" the selected audit
events (see above) will not be written to the event
log. Consequently, they cannot be retrieved using the
history method of the
WfExecutionObjects created by
this process (see history()). The
selected audit events will still be delivered to audit
handlers (see remarks at the end of this section).
Example:
...
<package>
...
<WorkflowProcesses>
<WorkflowProcess>
...
<Activities>
...
</Activities>
<ExtendedAttributes>
<ExtendedAttribute Name="RemoveClosedProcess" Value="MANUAL"/>
<ExtendedAttribute Name="Debug" Value="True"/>
<ExtendedAttribute Name="AuditEventSelection" Value="AllEvents"/>
<ExtendedAttribute Name="StoreAuditEvents" Value="True"/>
</ExtendedAttributes>
</WorkflowProcess>
</WorkflowProcesses>
<ExtendedAttributes>
<ExtendedAttribute Name="RemoveClosedProcess" Value="AUTOMATIC"/>
</ExtendedAttributes>
</package>
...
Filtering out events or disabling the audit trail causes the observable behaviour of the process at the API to deviate from the standard. It may nevertheless be a useful option as it reduces the number of database transactions significantly and thus increases throughput. Especially when using workflow processes to work off batches of datasets, a workflow specific logging provided by the invoked tools will most likely be more useful than the default audit trail.
Extensions:
DeferredChoice
if set to true the
AND-split of an activity will be
executed as deferred choice. See Section 4.3.5, “Deferred choice” for an explanation of the
semantics.
The definition and interpretation of the priority of a WfExecutionObject (e.g. a Process) differs between WfMC and OMG. According to WfMC, the priority can be any natural number starting with zero and higher numbers represent higher priorities. Conforming to the OMG specification, the priority has to be an integer between 1 to 5 with 1 being the highest priority. We have chosen to support OMG's specification which means that the priority specified in the process XPDL must be an integer value between 1 and 5 with descending priority and the result of a priority request (see priority()) delivers the priority with equal semantic.
Since it is not defined how to obtain the category of the process manager from the XPDL description, we have chosen to interpret the package's Name attribute as being the category value. The same applies to the version attribute, which we have chosen to map to the element created within the process header definition.
Please note, that if you don't specify the script type for you package, it will default to "text/ecmascript" which is the most common used language for scripting within this context.
XPDL (XML Process Definition Language) defines the syntax and grammar for the description of workflow processes that can be imported into the WfMOpen engine. Unfortunately XPDL is not precise about the interpretation of some description elements. This chapter describes our interpretation of all XPDL language elements that are important for the definition of the process flow.
Usually a workflow consists of some or all of the following elements:
Activities that should be performed in a given order (successively and/or concurrently).
Transitions between activities (described by "from" and "to" declarations), defining the execution sequence.
Conditions for the transitions as criteria for the execution of the transition.
Since XPDL does not define attributes for marking the first or last activity within a workflow, we have chosen to use those activities to be initially started which are not referenced within a "to" declaration of any of the workflow's transitions. We think this is an obvious approach that does not restrict the number of inital activities. Usually there will be only one entry activity but you may also define several one's which will then be started concurrently. That implies, that there has to be at least one of those activities or nothing will be started at all (in fact, a warning will report such a condition on import of the workflow description).
The workflow engine considers a running process as finished when there is nothing more to do, i.e. when after the completion of an activity there is no other activity currently running and no other activity to start (for a detailed description of process and activity states see Section 2.1, “States of processes and activities”).
The simplest case of a workflow is one with just a single activity, thus defining the start and end point. As soon as a second activity is added that should run after the completion of the first, a transition between the two activities has to be defined. A transition has a "from" and a "to" attribute, referencing start and target of the connection. Once the "from" activity is completed, the "to" activity is started (assuming there are no conditions defined).
In real life, workflows do not just incorporate activities that will be started one after the other but there may be activities to be started concurrently or choices of activities depening on certain conditions.
There are typically two different situations to be dealt with when there is more than one subsequent activity:
XOR-Split: One of many activities may be selected at runtime depending on certain conditions.
AND-Split: Some of many activities may be selected at runtime depending on certain conditions.
The workflow engine expects a boolean to be returned. That means, if more than one line of code is defined only the last one defines the condition. Prior statements may be used e.g. for debugging purposes. Note that conditions are evaluated exactly once when the "from" activity is completed.
Example:
...
<Condition Type="CONDITION">
java.lang.System.out.println ("counter is " + Counter);
Counter < 3
</Condition>
...
Since XOR-Splits are used to select one of many activities
although more than one of the given condition may evaluate to
"true", an evaluation order has to be defined. This is done
within the TransitionRestrictions of the
activity. As soon as the first condition matches, this
transition is chosen, the target activity is started and no
further evaluation is performed.
...
<WorkflowProcess Id="XorSplitSample">
<ProcessHeader/>
<DataFields>
<DataField Id="avg_payroll" IsArray="FALSE">
<DataType>
<BasicType Type="INTEGER"/>
</DataType>
</DataField>
<DataField Id="test_payroll" IsArray="FALSE">
<DataType>
<BasicType Type="INTEGER"/>
</DataType>
</DataField>
</DataFields>
<Activities>
<Activity Id="check_payroll">
<Implementation>
<No/>
</Implementation>
<TransitionRestrictions>
<TransitionRestriction>
<Split Type="XOR">
<TransitionRefs>
<TransitionRef Id="granted"/>
<TransitionRef Id="declined"/>
</TransitionRefs>
</Split>
</TransitionRestriction>
</TransitionRestrictions>
</Activity>
<Activity Id="decline_salary_increase">
<Implementation>
<No/>
</Implementation>
</Activity>
<Activity Id="accept_salary_increase">
<Implementation>
<No/>
</Implementation>
</Activity>
</Activities>
<Transitions>
<Transition Id="declined" From="check_payroll" To="decline_salary_increase">
<Condition Type="OTHERWISE"/>
</Transition>
<Transition Id="granted" From="check_payroll" To="accept_salary_increase">
<Condition Type="CONDITION">
avg_payroll < test_payroll
</Condition>
</Transition>
</Transitions>
</WorkflowProcess>
...
For AND-Splits no evaluation order is needed, since each transition with a condition evaluating to "true" is chosen and the target activity is started. Note that the workflow engine will start each of those activities in a different thread so that they are performed simultaneously.
As for splitting there a also typically two different situations to be dealt with when joining parallel activities into a common thread:
XOR-Join: The first completed activity should trigger the joining activity. Note that the joining activity starts parallel to any predecessing activity, not yet completed.
AND-Join: The joining activity is triggered as soon as all predecessing activities are completed. This situation may also be described as "synchronization" of acitities.
Since predecessing activities and the joining activity are connected via transitions, you may also define conditions here that will be evaluated before triggering. So, within an XOR-Join, the first completed activity with a matching condition will trigger the joining activity. Note that, in contrast to the XOR-Split, no evaluation order is needed here since it is defined implicitely by the the race condition of the activites. Once the second of the predecessing activities is completed, the engine will detect that the joining activity is (no longer) in state "not started" and thus do nothing with it.
A special case of join occurs, when a predecessing activity is at the same time a subsequent activity of the joining activity. This situation describes a loop within a workflow which will be discussed in more detail in the following section.
Condition evaluation for outgoing transitions takes place when
an activity transitions to the closed...
state. This is important to know in order to understand the
behaviour of activities that use AND-Join.
If such an activity has two incoming transitions from
e.g. activities pre1 and
pre2 it may happen that
pre1 reaches its closed state long before
pre2. If the transition from
pre1 has a condition that depends on some
process relevant data item, the value of this data may have
changed after pre1 has reached the closed
state but before pre2 finishes. According
to the definiton above, the condition will be evaluated based on
the value at the time when pre1 reaches the
closed state, subsequent changes of the process relevant data
will not change the result of this evaluation[18].
Looping within a workflow means that the workflow comes back to an activity that has already been completed before. WfMOpen supports loops in a very straightforward way and without limitations concerning start and end points of loops[19].
There is no special attribute defining an activity or transition being part of a loop. Rather the workflow engine of WfMOpen detects a loop by tracking the running workflow. As soon as a transition targets an activity that has already been marked as "been on the path", this activity is considered as entry point of a loop (the activity must, of course, have an XOR-Join mode).
If the target activity is completed, the workflow engine first resets the state of all activites on the path that lead to that activity to "not started" and the (re-)starts the target activity.
Asynchronous deadlines constitute new independant threads. Thus the activity started by the deadline has an empty path. You can therefore not loop back to the activity that defined the deadline. You can loop back to the activity started by the asynchronous deadline e.g. to have it re-triggered by a later deadline (though you'll need an extra route activity because of join conditions).
Synchronous deadlines continue processing using the same thread. Thus all activities that have been adandoned due to the deadline are predecessors of the activity started because of the deadline (there may be more than one activity that is abandoned because of the deadline if the deadline occurs on a block activity). The simplest usage of this behaviour may be a synchronous deadline that points back to the synchronous activity, thus causing a maybe different assignment of resources.
WfMOpen supports the "deferred choice" pattern as described on
the workflow
patterns site. The pattern is implemented by defining an
optional extended attribute for activities with an
AND-split. E.g.:
...
<Activity Id="act1" Name="ACT1">
<Implementation>
<No/>
</Implementation>
<StartMode>
<Automatic/>
</StartMode>
<FinishMode>
<Automatic/>
</FinishMode>
<TransitionRestrictions>
<TransitionRestriction>
<Split Type="AND"/>
</TransitionRestriction>
</TransitionRestrictions>
<ExtendedAttributes>
<ExtendedAttribute Name="DeferredChoice">true</ExtendedAttribute>
</ExtendedAttributes>
</Activity>
All activities following the activity with the deferred choice
option set are started "preliminary". The activity (or tool
started by the activity) that first performs a modification of
the workflow engine's state automatically becomes the chosen
activity. Modification of state includes a tool's calls to
setResult() and
complete(), the completion of an activity
that has no implementation and the termination and abandoning of
an activity. All other preliminary chosen activities are reset
to the "not started" state (see Section 2.1, “States of processes and activities”) after
terminating any tools that are being run by these activities.
The preliminary choice implies the possibility that a tool
executed by an activity has already performed some work that
cannot be rolled back when the preliminary choice is revoked,
i.e. in the tool's implementation of
terminate(). A "deferred choice aware" tool
may therefore prematurely (i.e. before calling
setResult() or
complete()) force the eventual choice to be
made by calling choose() on the activity
(see choose()). An
example of such a case would be a user front-end where the
selection of an assigned activity (i.e. the begin of work) is
already decisive for the continuation of the process. If not
invoked as part of a deferred choice, the call to
choose() simply does nothing.
[15] In
order to allow a string describing a not well-formed document to
be parsed, an opening and closing tag
temporary-root is added before and after
the string and the corresponding node is removed from the result
after parsing. This should be transparent to the user unless
there is a parsing error. In this case you may find the tag
being mentioned in the error message (though it will never be
the cause of the problem).
[16] Note that this is really executed as a string comparison, i.e. you cannot use another prefix.
[17] Added in 1.3.4
[18]
WfMOpen versions up to 1.3.2 behaved differently. If an
activity with AND-Join was triggered by a transition, the
conditions of all other incoming transitions would be
evaluated at that point in time (with evaluation errors for
OTHERWISE and for abandoned predecessor
activities). This behaviour is not an option as it can lead
to unexpected results under certain circumstances. Starting
with 1.3.3, WfMOpen behaves as defined above (including
proper handling of OTHERWISE and
abandoned activities).
[19] Note that you may not loop back to an entry activity, i.e. an activity that you want to be started when the process is started, because by doing so it will be no longer be detected as entry activity (remember, that the engine looks for activities that is not referenced within a "to" declaration of any transition!).
Table of Contents
Tools are the "workhorses" of a workflow process. They call backend systems, retrieve data from a database, process data etc. WfMOpen comes with a set of ready-to-use tools and allows you to add your own tools using some well-defined APIs.
The tools included in the distribution are:
this tool can be used to build a web dialog for filling out data fields (see Section 5.2, “The XForms Tool”).
these tools implements an interface to the Rhino JavaScript interpreter (see Section 5.3, “JavaScript tools”).
this tool implements an interface to the Jelly XML interpreter (see Section 5.4, “Jelly tool”).
this is an extension of the Jelly tool that allows easy LDAP queries and manipulation (see Section 5.4.2, “LDAP tag library”).
this tool implements an interface to the javax mailing service (see Section 5.5, “Mail tool”).
this tool implements a tool that invokes a xslt processor dynamically (see Section 5.6, “XSLT tool”).
this tool implements a tool that invokes SOAP based web services dynamically (see Section 5.7, “Generic SOAP tool”).
this tool implements a tool that invokes web services with SOAP RPC style dynamically (see Section 5.8, “RPC SOAP tool”).
this tool waits for a given time span, optionally in an interruptable way (see Section 5.9, “Wait tool”).
this tool invokes a method of an MBean (see Section 5.10, “MBean invocation tool”).
Tools that support message oriented communication with process instances (see Section 5.12, “Channel based access”).
The following sections describe the predefined tools and provide some hints for implementing additional tools[20].
If an activity requires human interaction such as providing some data in a form, the activity may submit a form and associated initial data to the XForms tool. Then, the user associated with the activity invokes the XForms tool in order to manually complete the activity.
The XForms tool is an example of asynchronous application invocation and therefore consists of two components. The first component, the tool agent, is invoked by the workflow engine and puts information about the form to complete and the assignee in the database. The second component, the actual application, consists of a portlet. Initially, it lists all activities assigned to the currently logged in user. The display distinguishes between activities that are directly assigned to the current user and activities that are indirectly assigned, i.e. that are assigned to groups or roles the current user belongs to.
The web form for a specific activity is selected and displayed by selecting the link in the "Activity" column. The form may then be used to enter the required data. When the form is submitted, the entered data is used as result data of the activity and the activity is set to state "completed".
An application of type "XFormTool" is specified in the process
definition as described in Section 4.2.5.1, “Extentions of Application Declaration”,
with the extended attribute
Implementation referencing the
class
de.danet.an.xformstool.Submitter.
The tool agent has a mandatory property named
Form that defines the XForm
(see XForms
specification) to display.
A complete example of such an application definition is shown below:
...
<Application Id="SimpleForm">
<Description>
Simple data form.
</Description>
<FormalParameters>
<FormalParameter Id="input" Mode="OUT">
<DataType><BasicType Type="STRING"/></DataType>
</FormalParameter>
</FormalParameters>
<ExtendedAttributes>
<ExtendedAttribute Name="Implementation">
<vx:ToolAgent Class="de.danet.an.xformstool.Submitter"
Execution="SYNCHR">
<vx:Property Name="Form">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xforms="http://www.w3.org/2002/xforms"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<head>
<title>Simple Form</title>
<style>
.SimpleForm .control { display:block; }
.SimpleForm .control label {
display:block; float:left; width:9em; }
</style>
<xforms:model>
<!-- Instance will be inserted here -->
<!-- override/add some bindings -->
<xforms:bind id="SimpleForm:input"
nodeset="ActualParameter[@name='input']"
constraint="string-length(.) > 0"
required="true()"/>
</xforms:model>
</head>
<body class="SimpleForm">
<xforms:group id="C-3" appearance="minimal">
<xforms:label id="C-4">Simple Form</xforms:label>
<xforms:input bind="SimpleForm:input" incremental="true">
<xforms:label>Input </xforms:label>
<xforms:alert>Field may not be empty!</xforms:alert>
<xforms:hint>Please enter something.</xforms:hint>
<xforms:help id="C-7h">Use the <b>keyboard</b>.</xforms:help>
</xforms:input>
<xforms:submit submission="action">
<xforms:label>Complete</xforms:label>
</xforms:submit>
</xforms:group>
</body>
</html>
</vx:Property>
</vx:ToolAgent>
</ExtendedAttribute>
</ExtendedAttributes>
</Application>
...
The form definition consists of XHTML and XForms elements. It
must have an <xhtml:html> as root
element. The nested <xhtml:head> may
have a <xhtml:title>. If specified,
it is displayed as title of the portlet when the form is
selected and displayed. Any specified styles are copied to the
the portal page[21]. To avoid ambiguities between
forms display in different portlets on the same page, the style
declarations should be made unique by starting the match
expression with the application's id as a class. The HTML
rendered for the form in the portlet will have an enclosing
<div> with the application's id as
class attribute. CSS styles specified with this class name in
the match expression will therefore only apply to this form and
no other form on the same portal page.
As last child of <xhtml:head>, the
tool automatically generates and inserts an XForms model derived
from the formal parameters. The model looks like this:
<xforms:model>
<instance xmlns="">
<ActualParameters xmlns="">
<ActualParameter name="input"/>
</ActualParameters>
</instance>
<submission xmlns="http://www.w3.org/2002/xforms"
action="invoke:application" id="action" method="" replace="none"/>
<xforms:bind id="SimpleForm:input"
nodeset="ActualParameter[@name='input']"/>
</xforms:model>
For each formal parameter, an element
<ActualParameter> is generated with
an attribute "name" that equals the id of
the formal parameter. In addition, a binding is generated for
each formal parameter with an id derived from the combination of
the application id and formal parameter id. These generated
bindings may be overridden and supplemented with bindings
supplied in the XForm description as shown in the example above.
Finally, the form defines the
<xhtml:body> with the actual GUI
elements. The form is processed with Chiba XForms processor (see
Chiba home
page). See the Chiba documentation for details about
how HTML generated from the XForm definition.
The JavaScript tools can be used to execute embedded java script code (see example in Section 4.2.5.1, “Extentions of Application Declaration”). The tool comes in two flavours. Both support JavaScript 1.5 with E4X. They differ in their handling of arguments.
The class
de.danet.an.workflow.tools.rhino.JSExecutor
provides an implementation that references formal parameters of
the tool invocation in the script via
args["parameter_id"].
Parameters of numeric type and of type String
are made available as the corresponding JavaScript
objects. Parameters of type Date and
SchemaType are not converted. Rather the
internally used Java representation
(java.util.Date or
de.danet.an.workflow.api.SAXEventBuffer
respectively, see Section A.2.48, “Interface SAXEventBuffer”) is
passed to the JavaScript interpreter. Usage of this flavour of the
tool is considered deprecated. However, the tool will remain part
of WfMOpen.
Class
de.danet.an.workflow.tools.rhino.JSExecutor2,
available since version 1.3.4, represents the modern flavour of
the tool. It provides the formal parameters declared for the tool
as top-level JavaScript variables. In addition to the convertions
of numeric types and strings, this version of the tool also
converts parameters of type Date to
JavaScript Date objects and parameters of
SchemaType to JavaScript (E4X) XML objects.
Besides the arguments, the JavaScript execution environment
provides the global variable scriptingContext.
This context defines the following methods and properties.
The method abandon(String) (see Section A.3.11, “Interface ToolAgentContext”).
Invoking this method causes the JavaScript execution to be
terminated[22] and the exeption name
used as parameter to be passed to the condition evaluation
for transitions to subsequent activities.
The property activityUniqueKey. This
property is of type ActivityUniqueKey
(see Section A.2.11, “Class ActivityUniqueKey”)
and may be used to obtain some information about the
invoking activity.
As the implementation of the JavaScript tool is based on
Mozilla's Rhino
implementation (see http://www.mozilla.org/rhino), you may use all
features of this package (e.g. call static member functions
of java classes within the JavaScript code). Example:
java.lang.System.out.println
("Waiting " + args["ms"] + "ms");
The Jelly tool can be used to execute Jelly script code (see Jelly documentation). A Jelly script is basically XML that consists of tags that are either copied to the output or processed by the Jelly interpreter. Processing tags may result in the generation of additional XML nodes in the output.
The first formal parameter of a Jelly tool declaration must be an
OUT parameter of
SchemaType. It receives the result, i.e. the
generated XML. The other formal parameters of the tool invocation
may be of arbitrary type and are directly available as variables
within the Jelly script. Values assigned to variables that
correspond to formal OUT or
INOUT parameters in the Jelly script will
change the values of the actual parameters upon tool completion.
Its SQL library makes Jelly the perfect tool for interfacing between XML data structures and an RDBMS. The library provides the same tags as the JSTL SQL tag library. The sample script below retrieves the names of the process definitions from the Workflow engine's database[23].
...
<Application Id="DBJelly">
<Description>Database Jelly test</Description>
<FormalParameters>
<FormalParameter Id="result" Mode="OUT">
<DataType>
<SchemaType/>
</DataType>
</FormalParameter>
</FormalParameters>
<ExtendedAttributes>
<ExtendedAttribute Name="Implementation">
<vx:ToolAgent Class="de.danet.an.workflow.tools.JellyTool">
<vx:Property Name="Script">
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:x="jelly:xml"
xmlns:html="jelly:html" xmlns:sql="jelly:sql"
xmlns:sqlx="jelly:de.danet.an.util.jellytags.Library">
<sql:setDataSource dataSource="jdbc/WfEngine"/>
<sqlx:query var="results">
SELECT PackageId, ProcessId FROM ProcessDefinition
WHERE PackageId = ?
<sql:param value="jellytests"/>
</sqlx:query>
<dataSet>
<j:forEach items="${results.rowsByIndex}" var="row">
<row>
<j:forEach var="columnName"
items="${results.columnNames}" indexVar="i">
<field column="${columnName}">${row[i]}</field>
</j:forEach>
</row>
</j:forEach>
</dataSet>
</j:jelly>
</vx:Property>
</vx:ToolAgent>
</ExtendedAttribute>
</ExtendedAttributes>
</Application>
...
The example script uses a special query tag.
This tag uses a PreparedStatement wrapper
from the Danet utility library that handles large strings
correctly even if you use Oracle as RDBMS. A similar
update tag is available in the namespace
jelly:de.danet.an.util.jellytags.Library as
well.
Although it is possible to define "stand-alone" data sources for
your RDBMS using the SQL tag library, it is much better to use the
pooled connections managed by the application server. The SQL tag
library supports access to these pools via JNDI, as shown in the
example. Note that "java:comp/env/" is
prepended before the data source name (so the lookup made in the
sample code is
"java:comp/env/jdbc/WfEngine"). The data
source must therefore be defined as a logical name in an EJB
context. All tools are invoked from a business method of the
InvocationHelperEJB. Therefore, if you need
additional data sources, you have to define them in this EJB's
context (either by modifying ejb-jar.xml and
its associated application server specific descriptor manually or
by using some tool from your application server vendor).
As the tool is executed in the context of an EJB's business
method, the <transaction> tag should
not be used. The business method that invokes the tool has the
container managed transaction attribute set. Thus the application
server automatically wraps all database queries and updates
executed during the tool invocation in a transcation.
Note that there are a lot of tag libraries available for Jelly. Some of these interface to quite complex libraries. The demo applications (see Appendix C, The demo applications) includes only the tag libraries "jsl", "log", "sql", and "xml". Of course, you are free to re-pack the application with more libraries included.
Thinking about an LDAP tool, we found that a query tool can be implemented in a straight forward manner. A tool that also supports LDAP manipulation, however, would require an unmanageable number of configuration properties to support the different kinds of queries imaginable. We have therefore implemented an LDAP tag library for Jelly that enables easy query and manipulation of an LDAP directory.
All query and update tags require a connection to the LDAP
server. This connection can be obtained with the
<ldap:setInitialContext>. The usage
pattern is:
<ldap:setInitialContext
var="ctx"
xmlns:ldap="jelly:de.danet.an.util.jellytags.ldap.Library"
providerUrl="ldap://localhost:389"
securityPrincipal="cn=Manager,dc=my-domain,dc=com">
<ldap:environmentEntry name="java.naming.security.credentials"
value="${credential}"/>
</ldap:setInitialContext>
The <ldap:setInitialContext> tag
creates a connection (actually an initial
DirContext) and assigns it to the
variable named in attribute var. Nested
within the tag are <ldap:environmentEntry
name="..." value="..."/> tags that specify
values for the environment used to obtain the initial context
(see Sun's JNDI specification for details).
For convenience, some environment entries may also be specified as attributes.
Table 5.1. Entries that can be specified as attributes
| Entry name | Attribute |
|---|---|
java.naming.factory.initial | initialContextFactory |
java.naming.provider.url | providerUrl |
java.naming.security.principal | securityPrincipal |
java.naming.security.credentials | securityCredentials |
java.naming.factory.initial has a
preset default of
com.sun.jndi.ldap.LdapCtxFactory.
The <ldap:query> queries the LDAP
server for a specific entry or a list of entries. The usage
pattern is:
<ldap:query ldapContext="${ctx}"
dn="ou=People,dc=my-domain,dc=com"
filter="(uid=lipp)" attributes="cn, uid,gecos"/>
The attribute ldapContext must be
specified and must refer to a previously created
context. Attribute dn must also be
given. It specifies the entry or the base for the directory
search. Attribute filter is optional. If
not specified, dn must refer to an entry
in the directory, else dn is used as base
for a search with filter. It
attributes is specified, only the comma
separated list of attributes of the entry or entries is
retrieved from the server, thus saving bandwidth and CPU cycles.
The data retrieved is output by the tag as an XML structure:
<queryResult dn="ou=People,dc=my-domain,dc=com"
filter="(uid=lipp)">
<entry dn="uid=lipp,ou=People,dc=my-domain,dc=com">
<attribute name="gecos">Michael N. Lipp</attribute>
<attribute name="uid">lipp</attribute>
<attribute name="cn">Michael N. Lipp</attribute>
</entry>
</queryResult>
This structure may be output directly or further
processes by Jelly. Here is a complete application declaration that
converts the retrieved data to a user record.
<Application Id="LDAPQuery">
<Description>Query fixed entry</Description>
<FormalParameters>
<FormalParameter Id="result" Mode="OUT">
<DataType>
<SchemaType/>
</DataType>
</FormalParameter>
</FormalParameters>
<ExtendedAttributes>
<ExtendedAttribute Name="Implementation">
<vx:ToolAgent Class="de.danet.an.workflow.tools.JellyTool">
<vx:Property Name="Script">
<j:jelly trim="false" xmlns:j="jelly:core" xmlns:x="jelly:xml"
xmlns:html="jelly:html" xmlns:log="jelly:log"
xmlns:ldap="jelly:de.danet.an.util.jellytags.ldap.Library">
<!-- You will probably not put this in the process description.
Use Jelly functions to obtain the password from e.g. JNDI
environment, a properties file or whatever password store suits
your application. -->
<j:set var="credential" value="********"/>
<!-- ldap:setInitialContext supports attributes
"initialContextFactory", "providerUrl", "securityPrincipal"
and "securityCredentials" as short-cuts.
More entries may be set in the environment used by using nested
"environmentEntry" tags, as shown. -->
<ldap:setInitialContext var="ctx" providerUrl="ldap://localhost:389"
securityPrincipal="cn=Manager,dc=my-domain,dc=com">
<ldap:environmentEntry name="java.naming.security.credentials"
value="${credential}"/>
</ldap:setInitialContext>
<!-- Execute the query and save the result document -->
<x:parse var="response">
<ldap:query ldapContext="${ctx}" dn="ou=People,dc=my-domain,dc=com"
filter="(uid=lipp)" attributes="cn, uid,gecos"/>
</x:parse>
<!-- Output the user record -->
<x:set var="userId" select="$response/queryResult/entry/@dn"
single="true" asString="true"/>
<x:set var="userName"
select="$response/queryResult/entry/attribute[@name='cn']"
single="true" asString="true"/>
<user id="${userId}" name="${userName}"/>
</j:jelly>
</vx:Property>
</vx:ToolAgent>
</ExtendedAttribute>
</ExtendedAttributes>
</Application>
Of course, part of the query criteria
(dn or the value in filter)
will usually be passed to the application as a parameter.
The tag <ldap:insert> inserts new
entries in the directory. The usage pattern is:
<ldap:insert ldapContext="${ctx}">
<entry dn="uid=test,ou=People,dc=my-domain,dc=com">
<attribute name="objectClass">top</attribute>
<attribute name="objectClass">account</attribute>
<attribute name="description">Just a test account</attribute>
</entry>
</ldap:insert>
The tag itself has only one attribute
ldapContext that references a previously obtained
LDAP connection. The entries to be added to the directory are nested
within the tag. They are formatted exactly as the results of a query.
This facilitates deriving new entries from existing entries.
The tag <ldap:update> updates
existing entries in the directory. The usage pattern is:
<ldap:update ldapContext="${ctx}" operation="replace">
<entry dn="uid=test,ou=People,dc=my-domain,dc=com"
operation="replace">
<attribute name="description" operation="replace">
Just an updated test account
</attribute>
<attribute name="organizationName">Testing</attribute>
</entry>
</ldap:update>
The tag itself has only one mandatory attribute
ldapContext that references a previously
obtained LDAP connection. An optional attribute
operation may be specified at the
ldap:update tag or for the
entry or for an
attribute. It controls whether the attribute is
replaced ("replace"), added
("add") or removed
("remove"). If no operation is specified
for a tag, the operation specified for the enclosing tag is
performed. ldap:update has a default operation
of "replace".
The tag <ldap:delet> deletes
existing entries in the directory. The usage pattern is:
<ldap:delete ldapContext="${ctx}">
<entry dn="uid=test,ou=People,dc=my-domain,dc=com"/>
</ldap:delete>
The tag itself has only one mandatory attribute
ldapContext that references a previously
obtained LDAP connection. The entries to be deleted are
specified as nested entry tags. Any
attribute tags nested within an
entry tag are simply ignored. This allows
using a query result directly as selection of entries to be
deleted.
The mail tool builds an interface to the javax mail facility and thus can be used to send text messages to any recipient. Formal parameters are interpreted in the following order of declaration:
address(es) of recipient(s)
subject
message
address of sender
Furthermore, in case that no actual valid sender can be given as formal parameter (e.g. the data field is not set), a default sender can be declared via a property of the tool agent.
Example:
...
<Application Id="MailTool2">
<FormalParameters>
<FormalParameter Id="recipient" Mode="IN">
<DataType>
<BasicType Type="STRING"/>
</DataType>
</FormalParameter>
<FormalParameter Id="subject" Mode="IN">
<DataType>
<BasicType Type="STRING"/>
</DataType>
</FormalParameter>
<FormalParameter Id="message" Mode="IN">
<DataType>
<BasicType Type="STRING"/>
</DataType>
</FormalParameter>
<FormalParameter Id="sender" Mode="IN">
<DataType>
<BasicType Type="STRING"/>
</DataType>
</FormalParameter>
<FormalParameter Id="status" Mode="OUT">
<DataType>
<BasicType Type="STRING"/>
</DataType>
</FormalParameter>
</FormalParameters>
<ExtendedAttributes>
<ExtendedAttribute Name="Implementation">
<vx:ToolAgent Class="de.danet.an.workflow.tools.MailTool2"
xmlns:vx="http://www.an.danet.de/2009/XPDL-Extensions1.1">
<vx:Property Name="DefaultSender">test@WfMOpen.com</vx:Property>
</vx:ToolAgent>
</ExtendedAttribute>
</ExtendedAttributes>
</Application>
...
The mail provider to be used is determined by a JNDI lookup
using the logical name
java:comp/env/toolagents/mailtool/Mail in the
context of the InvocationHelperEJB (see Section 3.5.3, “Accessing JNDI”). As distributed, WfMOpen binds
this logical name in the JBoss specific deployment descriptor to
the global JNDI entry java:/WfMOpenMail. Make
sure that this entry exists. For JBoss, we recommend to create a copy of
$JBOSS_HOME/server/
(e.g. as configuration/deploy/mail-service.xmlwfmopen-mail-service.xml), set the entry
JndiName within the file to
java:/WfMOpenMail, and adjust the entry
mailhost.smtp.host (minimal configuration).
This tool can be used to transform xml content with an XSLT
processor. The transformation is done using the JAXP 1.1 API,
which introduces an abstract layer for the transformation process.
The stylesheet to be used in the transformation may either be
given by a URL or an inline definition using the property
XSLT. The two cases are
distinguished by checking whether the
XSLT property defines a valid URL
or not. If no XSLT property is
given, the output document is the same as the input document (this
allows the tools to be used as a merger or value extractor, see
below). The stylesheet must produce a well formed xml-document for
the tool to work correctly.
The first formal parameter containing xml content defines the
content to be transformed by the tool. Additional input parameters
are used to set stylesheet parameters. The result of the
transformation is assigned to all formal output parameters,
applying an additional mapping if defined using the
Mappings property.
Example:
...
<Application Id="XSLT">
<Description>
</Description>
<FormalParameters>
<FormalParameter Id="inlist" Mode="IN">
<DataType>
<SchemaType/>
</DataType>
</FormalParameter>
<FormalParameter Id="result" Mode="OUT">
<DataType>
<BasicType Type="STRING"/>
</DataType>
</FormalParameter>
</FormalParameters>
<ExtendedAttributes>
<ExtendedAttribute Name="Implementation">
<vx:ToolAgent Class="de.danet.an.workflow.tools.XSLTTool"
xmlns:vx="http://www.an.danet.de/2009/XPDL-Extensions1.1">
<vx:Property Name="XSLT" xmlns="">
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:param name="city" select="'Darmstadt'"/>
<xsl:template match="row">
<record>
<painter><xsl:value-of select="@painter"/></painter>
<title><xsl:value-of select="@title"/></title>
<year><xsl:value-of select="@year"/></year>
<size><xsl:value-of select="@size"/></size>
<city><xsl:value-of select="$city"/></city>
</record>
</xsl:template>
<xsl:template match="table">
<table>
<xsl:apply-templates select="row"/>
</table>
</xsl:template>
</xsl:stylesheet>
</vx:Property>
<vx:Property Name="Mappings">
<vx:OutputMappings>
<vx:Parameter Name="result" Select="/table/record[1]/painter"/>
</vx:OutputMappings>
</vx:Property>
</vx:ToolAgent>
</ExtendedAttribute>
</ExtendedAttributes>
</Application>
...
As can be seen in the example, an XPath expression can be defined
for each output parameter. The XPath expression is applied to the
transformation result, yielding a derived result that is then
assigned to the output parameter referenced in the output mappings
section. The output parameters may be of
SchemaType or BasicType
STRING, INTEGER,
FLOAT, DATETIME or
BOOLEAN. For types datetime, float and
boolean, the XPath expression must evaluate to a string that
matches the format of the corresponding XSD type. Parameters of
type integer are evaluated by applying the XPath
number function to the result of the
selection and using the integer part of the returned value.
As an additonal feature, the tool supports merging XML content from different input parameters before the transformation is applied.
If the first formal parameter is of type
STRING, its value defines the tag value for a
root element of the intermediate content to be created. Any
additional formal input parameters of type
SchemaType will be added under this new root
element in order of appearance.
For example, calling the tool with a first input parameter "Root"
and two additional input parameters
<doc1><value1>...</value1></doc1>
and
<doc2><value2>...</value2></doc2>
results in an intermediate document
<Root><doc1><value1>...</value1></doc1><doc2><value2>...</value2></doc2></Root>
to which the transformation is applied.
This tool can be used to execute arbitrary SOAP requests. It must
be declared with a formal IN parameter of
SchemaType named
body. The XML passed into this parameter will
be literally copied into the
<soapenv:Body> section of the SOAP
request. Another formal IN parameter of
SchemaType named header
may optionally be declared and can be used to add content to the
<soapenv:Header> section of the SOAP
request. Another formal IN parameter of type
STRING named httpHeaders
may optionally be declared and can be used to specify additional
HTTP headers for the request. The string must consist of "key:
value" pairs separated by newline characters. Note that the value
of the special HTTP header "SOAPAction" will
automatically be surrounded by double quotes, so don't use double
quotes when specifying it.
Upon tool invocation, the request will be sent to the endpoint
specified as a property. Output parameters may be specified to
receive the complete result of the invocation (i.e. a tree with
root node <soapenv:Envelope>) or parts
of the result. The mapping of result values to output parameters
is configured as described for the XSLT tool (see Section 5.6, “XSLT tool”).
Example:
...
<Application Id="stockQuote">
<Description>
</Description>
<FormalParameters>
<FormalParameter Id="body" Mode="IN">
<DataType>
<SchemaType/>
</DataType>
</FormalParameter>
<FormalParameter Id="result" Mode="OUT">
<DataType>
<SchemaType/>
</DataType>
</FormalParameter>
</FormalParameters>
<ExtendedAttributes>
<ExtendedAttribute Name="Implementation">
<vx:ToolAgent Class="de.danet.an.workflow.tools.soap.GenericSoapClient">
<vx:Property Name="Endpoint">
http://localhost:8181/soapsrvdemo/StockQuoteService.jws
</vx:Property>
<vx:Property Name="Mappings">
<vx:OutputMappings>
<vx:Namespaces>
<vx:Namespace Prefix="soapenv"
Uri="http://schemas.xmlsoap.org/soap/envelope/"/>
</vx:Namespaces>
<vx:Parameter Name="result" Select="/soapenv:Envelope/*"/>
</vx:OutputMappings>
</vx:Property>
</vx:ToolAgent>
</ExtendedAttribute>
</ExtendedAttributes>
</Application>
...
If you are behind a firewall and want to access web services
outside your intranet, it may be necessary to tell the application
server (i.e. the virtual machine running it) about the proxy for
your http connection. For JBoss the information can be provided as
follows (see "J2SDK
Networking Properties"):
JAVA_OPTS="... -Dhttp.proxyHost=<PROXY HOST>
-Dhttp.proxyPort=<PORT>
-Dhttp.nonProxyHosts=localhost|*.your.domain" ./run.sh
If calling the web service results in a
SOAPException that indicates that the
server is unavailable, the tool raises a
CannotExecuteException with a
java.rmi.ConnectException as its
cause. This may be mapped to a process level exception as
described in Section 3.5.4, “Exception handling”.
This tool can be used to execute a method of a WSDL description
that defines an RPC style SOAP service. The WSDL description may
either be given by a URL or an inline definition via the property
WSDL. The discrimination between
the two cases is done by checking whether the
WSDL property defines a valid URL
or not. Formal parameters to the tool invocation define the method
name (first parameter) and the appropriate parameters to the
method call.
Example:
...
<Application Id="stockQuote">
<Description>
</Description>
<FormalParameters>
<FormalParameter Id="symbol" Mode="IN">
<DataType>
<BasicType Type="STRING"/>
</DataType>
</FormalParameter>
<FormalParameter Id="Result" Mode="OUT">
<DataType>
<BasicType Type="FLOAT"/>
</DataType>
</FormalParameter>
</FormalParameters>
<ExtendedAttributes>
<ExtendedAttribute Name="Implementation">
<vx:ToolAgent Class="de.danet.an.workflow.tools.soapclient.SOAPClient"
xmlns:vx="http://www.an.danet.de/2009/XPDL-Extensions1.1">
<vx:Property Name="WSDL">
<wsdl:definitions
targetNamespace="http://brian.an.danet.de:8080/soapsrvdemo/StockQuoteService.jws"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:apachesoap="http://xml.apache.org/xml-soap"
xmlns:impl="http://brian.an.danet.de:8080/soapsrvdemo/StockQuoteService.jws"
xmlns:intf="http://brian.an.danet.de:8080/soapsrvdemo/StockQuoteService.jws"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:message name="getQuoteResponse">
<wsdl:part name="getQuoteReturn" type="xsd:float"/>
</wsdl:message>
<wsdl:message name="getQuoteRequest">
<wsdl:part name="symbol" type="xsd:string"/>
</wsdl:message>
<wsdl:portType name="StockQuoteService">
<wsdl:operation name="getQuote" parameterOrder="symbol">
<wsdl:input message="impl:getQuoteRequest" name="getQuoteRequest"/>
<wsdl:output message="impl:getQuoteResponse" name="getQuoteResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="StockQuoteServiceSoapBinding"
type="impl:StockQuoteService">
<wsdlsoap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="getQuote">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="getQuoteRequest">
<wsdlsoap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://DefaultNamespace" use="encoded"/>
</wsdl:input>
<wsdl:output name="getQuoteResponse">
<wsdlsoap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://brian.an.danet.de:8080/soapsrvdemo/StockQuoteService.jws"
use="encoded"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="StockQuoteServiceService">
<wsdl:port binding="impl:StockQuoteServiceSoapBinding"
name="StockQuoteService">
<wsdlsoap:address
location="http://localhost:8080/soapsrvdemo/StockQuoteService.jws"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
</vx:Property>
<vx:Property Name="Method">getQuote</vx:Property>
</vx:ToolAgent>
</ExtendedAttribute>
</ExtendedAttributes>
</Application>
...The hints about firewalls described in Section 5.7, “Generic SOAP tool” apply to this tool as well.
When calling the web service results in a
java.rmi.RemoteException, the tool raises a
CannotExecuteException with the
RemoteException as its cause. In addition,
the tool establishes an exception mapping of
java.rmi.RemoteException to a process level
exception "RemoteException" (see Section 3.5.4, “Exception handling”). This reflects the
assumption that the unavailability of the web service is a
condition that is to be handled at the process level and cannot be
worked around by simply repeating the invocation (as is usually
done with RemoteExceptions).
Sometimes, further processing in a workflow process must be delayed until some date is reached. This can be achieved with the WaitTool.
In its simplest form, the wait tool is defined as:
...
<Application Id="SimpleWait">
<Description>Waits for a timer to expire</Description>
<FormalParameters>
<FormalParameter Id="waitUntil" Mode="IN">
<DataType>
<BasicType Type="DATETIME"/>
</DataType>
</FormalParameter>
</FormalParameters>
<ExtendedAttributes>
<ExtendedAttribute Name="Implementation">
<vx:ToolAgent Class="de.danet.an.workflow.tools.timing.WaitTool"
xmlns:vx="http://www.an.danet.de/2009/XPDL-Extensions1.1"/>
</ExtendedAttribute>
</ExtendedAttributes>
</Application>
...When used in this way, the tool will simply wait until the given date/time. Note that waiting is not implemented by calling something like "sleep" for the execution thread. Rather a persistent timer is created. So it is safe to specify a date next week, next month or even in years[24]. A running wait tool will continue to run even after server restarts.
As an alternative, the tool may also be invoked with a single
parameter of type INTEGER or
DOUBLE instead of
DATETIME. In this case, it waits for the
specified number of seconds to pass after its invocation.
In some workflows, you need the possibility to end the waiting
prematurely. For these cases another version of the tool is
provided that actually consists of three tools. The first tool
creates a timer, returning a timer id. The second tool waits until
the timer has expired (i.e. the date/time specified on creation
has been reached). And the third tool may optionally be used to
terminate the timer prematurely. In order to be able to
distinguish regular and premature completion easily, the wait tool
is given an OUT parameter that is set to
EXPIRED (regular termination) or
CANCELED (premature termination).
Example:
...
<Application Id="TimerCreator">
<Description>Creates a timer</Description>
<FormalParameters>
<FormalParameter Id="timerId" Mode="OUT">
<DataType>
<BasicType Type="INTEGER"/>
</DataType>
</FormalParameter>
<FormalParameter Id="waitUntil" Mode="IN">
<DataType>
<BasicType Type="DATETIME"/>
</DataType>
</FormalParameter>
</FormalParameters>
<ExtendedAttributes>
<ExtendedAttribute Name="Implementation">
<vx:ToolAgent Class="de.danet.an.workflow.tools.timing.TimerCreator"
xmlns:vx="http://www.an.danet.de/2009/XPDL-Extensions1.1"/>
</ExtendedAttribute>
</ExtendedAttributes>
</Application>
<Application Id="TimerCanceler">
<Description>Cancels a timer</Description>
<FormalParameters>
<FormalParameter Id="timerId" Mode="IN">
<DataType>
<BasicType Type="INTEGER"/>
</DataType>
</FormalParameter>
</FormalParameters>
<ExtendedAttributes>
<ExtendedAttribute Name="Implementation">
<vx:ToolAgent Class="de.danet.an.workflow.tools.timing.TimerCanceler"
xmlns:vx="http://www.an.danet.de/2009/XPDL-Extensions1.1"/>
</ExtendedAttribute>
</ExtendedAttributes>
</Application>
<Application Id="Timing">
<Description>Waits for a timer to expire</Description>
<FormalParameters>
<FormalParameter Id="timerId" Mode="IN">
<DataType>
<BasicType Type="INTEGER"/>
</DataType>
</FormalParameter>
<FormalParameter Id="status" Mode="OUT">
<DataType>
<BasicType Type="STRING"/>
</DataType>
</FormalParameter>
</FormalParameters>
<ExtendedAttributes>
<ExtendedAttribute Name="Implementation">
<vx:ToolAgent Class="de.danet.an.workflow.tools.timing.WaitTool"
xmlns:vx="http://www.an.danet.de/2009/XPDL-Extensions1.1"/>
</ExtendedAttribute>
</ExtendedAttributes>
</Application>
...This tool supports the invocation of an MBean operation.
The tool is declared as:
...
<Application Id="SimpleInvoker">
<Description>Simple MBean invoker test</Description>
<FormalParameters>
<FormalParameter Id="result" Mode="OUT">
<DataType>
<BasicType Type="STRING"/>
</DataType>
</FormalParameter>
</FormalParameters>
<ExtendedAttributes>
<ExtendedAttribute Name="Implementation">
<vx:ToolAgent Class="de.danet.an.workflow.tools.MBeanInvoker">
<vx:Property Name="ObjectName">jboss:service=JNDIView</vx:Property>
<vx:Property Name="Operation">listXML</vx:Property>
</vx:ToolAgent>
</ExtendedAttribute>
</ExtendedAttributes>
</Application>
...
The tool looks up the MBean set in property
ObjectName and invokes its operation
Operation.
If the first declared formal parameter has mode
OUT or INOUT the result
of the operation invocation will be assigned to the actual
parameter. The parameter's type must match the return type of the
MBean's operation.
The second and subsequent parameters must have mode
IN or INOUT. All
parameters with mode IN or
INOUT (i.e. including the first) are passed
to the invoked operation. The parameter types are used to build
the signature used for operation lookup.
This tool supports the invocation of an EJB operation.
The tool is declared as:
...
<Application Id="EJBTool">
<FormalParameters>
<FormalParameter Id="JndiName" Mode="IN">
<DataType>
<BasicType Type="STRING"/>
</DataType>
</FormalParameter>
<FormalParameter Id="HomeClass" Mode="IN">
<DataType>
<BasicType Type="STRING"/>
</DataType>
</FormalParameter>
<FormalParameter Id="Method" Mode="IN">
<DataType>
<BasicType Type="STRING"/>
</DataType>
</FormalParameter>
<FormalParameter Id="Num1" Mode="IN">
<DataType>
<BasicType Type="INTEGER"/>
</DataType>
</FormalParameter>
<FormalParameter Id="Num2" Mode="IN">
<DataType>
<BasicType Type="INTEGER"/>
</DataType>
</FormalParameter>
<FormalParameter Id="AddResult" Mode="OUT">
<DataType>
<BasicType Type="INTEGER"/>
</DataType>
</FormalParameter>
</FormalParameters>
<ExtendedAttributes>
<ExtendedAttribute Name="Implementation">
<vx:ToolAgent
xmlns:vx="http://www.an.danet.de/2009/XPDL-Extensions1.1"
Class="de.danet.an.workflow.tools.EJBTool"/>
</ExtendedAttribute>
</ExtendedAttributes>
</Application>
...
The tool looks up the EJB with the JNDI name
JndiName and the home interface
HomeClass and invokes the operation
Method.
If the last declared formal parameter has mode
OUT or INOUT the result
of the operation invocation will be assigned to the actual
parameter. The parameter's type must match the return type of the
MBean's operation.
The fourth and subsequent parameters must have mode
IN or INOUT. All
parameters with mode IN or
INOUT (i.e. including the first three) are passed
to the invoked operation. The parameter types are used to build
the signature used for operation lookup.
Channel based access[25] provides channels for message oriented communication between a process instance and a client or between a process instance and its sub-processes.
Channels are named and associated with a process instance. They
need not be declared. Clients can obtain access to a channel from
the WorkflowService (see getChannel(de.danet.an.workflow.omgcore.WfProcess, java.lang.String)).
The channel may then be used to send messages to a receiver tool
or receive messages from a sender tool (see below). Messages are
simply passed from source to destination; there is no verification
that a message from a client to a process (i.e. to a receiver
tool) is followed by a message from the process (i.e. from a
sender tool) to the client or vice versa. The communication may be
initiated by any party: the process may create (or know about) a
client and intially send a message to it, or a client may create
or lookup a process that has started (or will start) a receiver
tool and send a message to it (see Section 5.12.3, “Generic HTTP Access” for a sample usage).
The receiver tool receives messages from a channel. It takes an
IN parameter of type
STRING that specifies the channel to listen
on, and an arbitrary number of additional
OUT parameters that receive the data sent
on the channel. The formal parameter names must match the keys
used in the map passed to the channel by the client (see sendMessage(java.util.Map)).
Normally, the receiver receives messages sent to the process it was started in. Sometimes, however, it is useful to structure a workflow process by using subflows. If the activities separated into the subflow include the usage of a receiver tool, the receiver tool listens on the wrong process, as the client does not (and should not) know about the separation in main process and subflow and keeps sending the messages to the main process.
The receiver tool therefore has a property
"ListenerIndex" that can be used to make
the receiver listen for messages sent to one of the requesting
processes of the current process (i.e. processes the current
process is a subflow of). If set, the property must be an
integer. 0 (zero) is the top requester, i.e. the process at the
end of the chain of requesting processes[26]. A positive integer specifies a process
relative to the current process (e.g. "1" is the requester, "2"
is the requester of the requester) while a negative integer
specifies a subflow relative to the top process.
Example:
...
<Application Id="TopReceiverTool">
<Description>Receive data from a channel accessor</Description>
<FormalParameters>
<FormalParameter Id="channel" Mode="IN">
<DataType>
<BasicType Type="STRING"/>
</DataType>
</FormalParameter>
<FormalParameter Id="message" Mode="OUT">
<DataType>
<BasicType Type="STRING"/>
</DataType>
</FormalParameter>
</FormalParameters>
<ExtendedAttributes>
<ExtendedAttribute Name="Implementation">
<vx:ToolAgent Class="de.danet.an.workflow.tools.chabacc.Receiver"
xmlns:vx="http://www.an.danet.de/2009/XPDL-Extensions1.1">
<vx:Property Name="ListenerIndex">0</vx:Property>
</vx:ToolAgent>
</ExtendedAttribute>
</ExtendedAttributes>
</Application>
...
The sender tools sends messages on a channel. It takes an
IN parameter of type
STRING that specifies the channel to send
to, and an arbitrary number of additional
IN parameters used to pass the data to be
sent to the channel. The formal parameter names are used as keys
in the map returned to the client (see receiveMessage()). Note
that actual parameters are sent on the channel as passed to the
sender tool. This implies that parameters of type
SchemaType may be sent as SAX event buffer,
W3C DOM or JDOM, depending on the value of attribute
XMLParameterMode in the definition of the
sender tool (see Section 4.2.5.1, “Extentions of Application Declaration”).
Like the receiver tool, the sender tool may be configured to
send messages from a requesting process instead of the process
the tool was started in. This is done by setting the property
"OriginatorIndex". The value is interpreted
in the same way as described for the receiver tool above.
An additional property of the sender tool specifies whether messages
sent should also be delivered to receiver tools listening on the
channel used (by default, they are only delivered to
clients). This may e.g. be used at the end of a process to terminate
a receiver tool running "in parallel" (i.e. it has waited for
some kind of optional intervention from a client during
processing and is now sent some dummy message to complete the
process properly). Together with the
"ListenerIndex" and
"OriginatorIndex" properties, this may also
be used for communication between processes, e.g. a subflow
informing its requester about its state.
Example:
...
<Application Id="TopSenderTool">
<Description>Send a message to a channel accessor</Description>
<FormalParameters>
<FormalParameter Id="channel" Mode="IN">
<DataType>
<BasicType Type="STRING"/>
</DataType>
</FormalParameter>
<FormalParameter Id="message" Mode="IN">
<DataType>
<BasicType Type="STRING"/>
</DataType>
</FormalParameter>
</FormalParameters>
<ExtendedAttributes>
<ExtendedAttribute Name="Implementation">
<vx:ToolAgent Class="de.danet.an.workflow.tools.chabacc.Sender"
xmlns:vx="http://www.an.danet.de/2009/XPDL-Extensions1.1">
<vx:Property Name="LocalDelivery">True</vx:Property>
<vx:Property Name="OriginatorIndex">0</vx:Property>
</vx:ToolAgent>
</ExtendedAttribute>
</ExtendedAttributes>
</Application>
...To simplify the HTTP access to a longterm workflow process, as it may be useful for designing dialog driven applications, an "out-of-the-box" solution is provided by a generic HTTP servlet.
For an example, let us assume we'd like to design an application that enables users to subscribe and unsubscribe a service and to modify the service parameters. The user interface should be provided by HTML pages and the service will be described by a workflow process definition[27].
The components we need are:
An entry Web page for subscribing to a new service or requesting an existing service.
A process definition within the workflow engine, describing the actions of the service and providing HTML pages for user actions (e.g. modification of service parameters).
A (user based) connection between the workflow engine (i.e. a service) and the client HTML pages (i.e. the browser).
Subscribing to a new service is easy to implement, since it may simply be done by starting a new workflow process. But once the process is running, arrangements have to be made to make sure that the process performs its service duties and concurrently listens for service "update" events. The latter task can be performed using the Receiver Tool (see Section 5.12.1, “Receiver tool”) and the Sender Tool (see Section 5.12.2, “Sender tool”) within a concurrently running activity.
To simplify the (channel based) interaction with workflow processes via HTTP, a servlet is provided that
starts a new process — if needed — and provides a channel to it or
opens a channel to an already running process and
holds the channel within the session for further use and forwards responses from the process to the client.
By using this servlet, HTTP based client applications (e.g. using HTML pages) are very easy to design. The current page sends a request to the servlet and the successor page (code) is provided by the proper workflow activity through the servlet. No further application code is needed.
The servlet described above serves as an interface between the
client application and a workflow process. The communication
with the process uses a message channel named
"initiator")
[28].
To identify the process to connect with, some key information has to be provided within the request. The following request parameters are treated as key values:
WFM_packageID and
WFM_processID: package ID and process ID of the
associated process
WFM_dataItemName and
WFM_dataItemValue: name and value of data
item (data field) that should be used as a search criteria for
a process of the specified type (i.e. with the given package
and process ID).
Variations:
Only WFM_packageID and WFM_processID (beside application data) are provided.
A new process of the specified type is created and initialized with the application data. A new message channel is built up to this process. The process manager name and process key are stored in the session context for later use (see variation 3).
If no process
description with the given package and process id exists,
status code 400 will be
returned.
All above-mentioned WFM* parameters are provided. A
lookup is performed for the process matching the given data
item criteria. If none is found, a new process of the
specified type is created and initialized with the given
data item and the provided application data. The process
manager name and process key are stored in the session
context for later use (see variation 3). If no process
description with the given package and process id exists,
status code 400 will be
returned.
If a matching process is found, this process is used. The provided application data is sent to the process via a built-up message channel.
If no
message channel can be opened because the process is closed,
status code 410 will be
returned.
If
more than one matching process is found, status code
409 will be returned.
WFM_packageID and WFM_processID are not provided. It is assumed that the process should be used which has already been referenced within the session (see variation 1 or 2). Thus, the process manager name and process key that have been stored in the session context are used to build the connection to the process. The provided application data is sent to the process via the built-up message channel.
If no
message channel can be opened because the process ist either
closed or removed, status code 410 will
be returned.
If no process information is stored
in the session context, status code 400
will be returned.
An additional parameter WFM_waitForResponse is provided
with a value of "false" (not equal to
"true", to be precise). In this case,
the servlet will not wait for a response from the
process. It will only send data to a process or create a
new process as described above and then return a response
with no content.
The message received on the channel from the process (sent by
the process using the sender tool, see Section 5.12.2, “Sender tool”) may have one or more entries. If it has
only a single entry, this entry is considered to be the data to
be sent back to the HTTP client, independant of the entry's
name. If the message has more than one entry, there must be one
entry with key data containing the data to
be sent back or otherwise, status 500 will
be returned to the client. The data (i.e. the corresponding
formal parameter of the SenderTool) may be of type
STRING or
SchemaType. In the latter case, the XML
data is transformed to its string representation by the generic
HTTP servlet before it is sent to the HTTP client. Note that the
data must be provided as a SAX buffer, i.e. the sender tool
defined for sending the response to the servlet must have the
attribute XMLParameterMode set to
USE_SAX (see Section 4.2.5.1, “Extentions of Application Declaration”).
Additional entries supported in a message received by the generic HTTP servlet are:
doctype-system (STRING)Specifies the system identifier to be used in the document type declaration of the document resulting from the conversion of response data passed as XML to its string representation.
doctype-public (STRING)Specifies the public identifier to be used in the document type declaration of the document resulting from the conversion of response data passed as XML to its string representation.
invalidateSession (BOOLEAN)When set to true, the session associated with the request is invalidated. This may be used to dissociate a client from its associated process (if they are linked using information from the session context as described in 3), thus forcing the creation of a new process on the next request.
mimeType (STRING)
When set, overrides automatic derivation of the
response's mime type from the data to be sent. The
default is to send any data of type
SchemaType as
text/xml. If the data is of type
STRING and the string starts with a
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD
HTML" or "<!DOCTYPE HTML PUBLIC
\"-//IETF//DTD HTML" declaration, it is sent
as text/xml. Otherwise the mime
type ist set to application/data.
The generic HTTP servlet will accept POST
requests only, as all requests lead to a modification of the
server side state. There is, however, one exception to this
rule.
In order to get started with a process based Web application, you must present the user an initial page that allows him to click on a link to create a new process or to fill in and submit some information that identifies an existing process. Now, where does this start page come from? Of course, it can simply be created as static HTML and provided by any Web server (and for performance reasons, this will eventually be the solution in many cases). However, even if only as proof of concept, it should be possible to specify a complete Web application — including the start page — using XPDL.
As initial URLs (i.e. URLs that can be typed into a browser)
will always perform a GET request, the
generic HTTP servlet must support such a request for generating
the start page. As this is a "get started" request, it will
always create a new process, whose single purpose is to send
back the content of the start page and then complete
[29] (although there may
be cases that allow to continue the lifespan of this
process). To avoid complicated looking URLs, the generic HTTP
servlet uses extra path information instead of parameters to
specify the type (i.e. package id and process id) of the process
to be created. The first segment in the extra path information
denotes the package id, the second the process id. If the
process id is omitted, it defaults to boot,
if the package id is omitted also, it defaults to
chabacc_http_plain. Both defaults may be
altered by specifying the servlet init parameters
packagePathSegmentDefault and
processPathSegmentDefault respectively.
Some examples of using the generic HTTP servlet are included in the demo applications (see Appendix C, The demo applications).
[20]
Note that the application declarations in this section have
been updated to use the new namespace
http://www.an.danet.de/2009/XPDL-Extensions1.1
that has been defined for version 2.1.2. If you do not want to
specify a Handler attribute as described in
Section 4.2.5, “Defined extensions”, you may still use the old
namespace
http://www.an.danet.de/2002/XPDL-Extensions1.0.
[21] CSS styles can only be defined on the page level.
[22] This behaviour differs from the
behaviour defined for
ToolAgentContext.abandonActivity (see
abandonActivity(java.lang.String)),
which returns after passing the information to the workflow
engine and allows the Java programmer to asynchronously
cleanup resources.
[23] This is intended as an immediately (i.e. without setting up additional data sources) working example. Of course, you should never access the workflow engine's database directly, use the API instead!
[24] Consider a process contolling the complete lifetime cycle of a document. After all the initial creating, reviewing, revising and using the document, it may be necessary to archive the document for another 5 years before deleting it.
[25] "ChaBAcc" for short. We don't know how this sounds in other languages, but Germans usually tend to grin at the sound of this acronym for no specific reason.
[26] This may also be used if the process is not a subflow at all, as a process without a requesting process is considered top of the chain.
[27] We use an HTML browser as example here in order to make the explanation easy to follow. Of course, this mechanism becomes more thrilling if you imagine a voice browser instead of the HTML browser and VoiceXML instead of HTML. We have used the generic servlet in such a way and built some nice workflow based voice applications with WfMOpen.
[28]
So you have to make sure, that the SenderTool and the ReceiverTool
use a channel named
initiator as
well.
[29] Admittedly, this is less efficient than a static HTML page, but you need not set up a server for static HTML pages. It is a bit like a servlet serving static files: obviously Web servers like Apache can do it faster, but in many cases you want to avoid the effort of installing Apache or adding to its configuration only to provide a few files as part of your J2EE application.
Table of Contents
For assigning resources to activities, a workflow component relies on a resource assignment facility as described in Section 3.1, “Component structure” and Section 3.4, “Resource assignment SPI”. Such a facility is not part of the core workflow functionality.
As we felt our workflow component to be incomplete without at least a simple resource assignment service, we have included an implementation of such a service in the workflow component.
The sample assignment service implements the resource assignment API as specified by package de.danet.an.workflow.spis.ras. The factory class and its configuration parameters are described in de.danet.an.workflow.assignment.StandardResourceAssignmentServiceFactory. See the classes description for further information not covered in the current section.
The sample resource assignement service is bundled in the library
de.danet.an.workflow.defaultras.jar. Besides
the required classes, this jar contains the file
META-INF/services/de.danet.an.workflow.spis.ras.ResourceAssignmentServiceFactory
that defines the class
StandardResourceAssignmentServiceFactory as
an implementation of the resource assignment service. Thus the
sample resource assignment service is found as described in newInstance()
if the jar is included in the classpath of the EAR that comprises
the application. Usually, this is done by adding the jar as Java
module to application.xml.
The sample resource assignment service uses the participant type
and participant name from the process definition to select a
resource from a resource management service (RMS, see below). If
the participant type is HUMAN, it looks for a
user with the given name, if it is
RESOURCE_SET, it looks for a group with the
given name, and it it is ROLE it looks for a
role with the given name.
For selecting the resource from the RMS, the sample RAS relies on
the RMS to support queries of the form
"M:user_name",
"G:group_name" and
"R:role_name" (see below).
As a special case, if the participant type is
HUMAN and the extended attribute
"resource-selection" exists and its value is
"!:currentUser", then the
activity is assigned to the user that has created the process. The
participant definition thus looks like:
<Participant Id="currentUser" Name="Current User">
<ParticipantType Type="HUMAN" />
<ExtendedAttributes>
<ExtendedAttribute Name="resource-selection"
Value="!:currentUser"/>
</ExtendedAttributes>
</Participant>
As the syntax "!:currentUser"
suggests, there had been plans to specify sophisticated selection
rules here. Currently, we think that any usage of the workflow
engine that needs more sophisticated assignment than selecting a
person, a group or the process creator will need its own
implementation of a RAS anyway.
Thinking about resource assignment, it soon becomes obvious that a resource assignment service must know about the resources it can assign and thus must include or be based on a resource management service.
Resource management, however, is not a trivial task. As such, we cannot provide a useful resource management, even as a sample implementation, as part of the workflow component. In order to be nevertheless able to provide a sample resource assignment service, we have defined a formal interface to a resource management service in package de.danet.an.workflow.spis.rms. Note that only the sample resource assignment service depends on this interface, not the workflow engine. If you decide to replace the sample resource assignment service with your own implementation, you no longer have to provide a resource management service as defined by the resource management service interface (of course, you may use the interface in your implementation of a resource assignment service if it suits your needs).
A resource management service must implement a resource management
factory and a resource management service as defined in Section A.5.9, “Class ResourceManagementServiceFactory”
and Section A.5.8, “Interface ResourceManagementService”. An
implementation of ResourceManagementFactory
may require additional configuration properties to adapt the
service instances that it creates to the specific
environment. Usually, these properties are retrieved from JNDI
environment entries or from a Java properties file.
The WfMOpen implementation guarantees that the resource
management service factory is only used in the context of the
WorkflowEngineEJB. Therefore, if you use JNDI
environment entries to configure your factory, it is sufficient to
add those entries to the
WorkflowEngineEJB. Note that the guarantee to
use the resource management service factory in this context only
is implementation specific. Therefore the general SPI description
leaves the issue of which EJBs require the entries deliberately
open.
As has been described above, any RMS that is to be used with the
sample resource assignment service must support the queries
"M:user_name",
"G:group_name" and
"R:role_name" as parameter of the
selectResources method (see selectResources(java.lang.Object)).
The WfMOpen distribution provides several implementations of a resource management service. These are described in the following sections.
Unless a standards based approach is used (see below) user information is most likely kept in an RDBMS. WfMOpen therefore includes a generic implementation of a database based RMS that can be adapted to a wide range of database schemas.
The detailed description of this service and its configuration parameters can be found in de.danet.an.workflow.rmsimpls.dbrms.
The factory and service classes are bundled in the
de.danet.an.workflow.dbrms.jar which can
be found in $DIST/lib/wfcore/. Besides the
required classes, this jar contains the file
META-INF/services/de.danet.an.workflow.spis.rms.ResourceManagementServiceFactory
that defines the class
de.danet.an.workflow.rmsimpls.dbrms.DatabaseRmsFactory
as an implementation of the resource management service. Thus
the database based resource management service is found as described
in newInstance()
if the jar is included in the classpath of the EAR that
comprises the application. Usually, this is done by adding the
jar as Java module to application.xml.
The service must be configured by specifying the statements for the various resource queries. This is decribed in detail in de.danet.an.workflow.rmsimpls.dbrms.DatabaseRmsFactory.
In general, information about resources is often kept in Enterprise Information Systems (EIS). The preferred approach for accessing this kind of systems in J2EE is by using JCA. WfMOpen therefore provides a resource management system implementation that relies on a JCA datasource to obtain information about resources.
The implementation uses a generic RMS implemantation that must be combined with a specific resource adapter. The description of this EIS RMS service and its configuration parameters can be found in de.danet.an.workflow.rmsimpls.eisrms.
The factory and service classes are bundled in the
de.danet.an.workflow.eisrms.jar which can
be found in $DIST/lib/wfcore/. Besides
the required classes, this jar contains the file
META-INF/services/de.danet.an.workflow.spis.rms.ResourceManagementServiceFactory
that defines the class
de.danet.an.workflow.rmsimpls.eisrms.EisRmsFactory
as an implementation of the resource management service. Thus
the EIS based resource management service is found as
described in newInstance()
if the jar is included in the classpath of the EAR that
comprises the application. Usually, this is done by adding the
jar as Java module to application.xml.
The EIS RMS implements only the "front-end" of the resource management system. It relies on a resource adapter that implements a specific client API that is used by the EIS RMS to provide its services. While it might have been possible to use the standard CCI (Common Client Interface) as API of the resource adapter, we found that this would have caused considerable overhead without providing a significant benefit. We have therefore defined a specific application client interface (ACI) in de.danet.an.workflow.rmsimpls.eisrms.aci.
The following sections describe the resource adapter
implementation for the EIS RMS that are distributed with
WfMOpen. Each of these adapters can be found as
de.danet.an.workflow.*ra.rar in the
directory $DIST/lib/wfcore/ of the
distribution.
The resource adapters follow standard packaging rules and can be deployed in any JCA compliant application server.
This resource adapter obtains its information from three
properties files. The first is used to describe
users. Entries have the format
"user=password". The
password is without significance for the adapter. The format
has been chosen to mach the requirements of the file based
authentication module of JBoss. This allows the file to be
used for both authentication and resource definition.
The second and third file describe roles and groups
respectively. The format for entries is
"user=role1,
role2, ..." (or
"user=group1,
group2, ..."). Again, the file
describing the roles can also be used for role management in
the file based authentication module of JBoss.
The files are made known to the resource adapter in its configuration. The properties to specify for deployment are:
PropertiesDirUrlThe directory that hold the properties files.
UsersPropertiesFileThe file that defines the users.
RolesPropertiesFileThe file that defines the roles.
GroupsPropertiesFileThe file that defines the groups.
A typical deployment configuration file for JBoss is shown below.
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- The properties based RMS resource adaptor service configuration -->
<connection-factories>
<no-tx-connection-factory>
<jndi-name>DefaultWfMOpenRmsRA</jndi-name>
<rar-name>
de.danet.an.plutoportalapp.ear#de.danet.an.workflow.propsrmsra.rar
</rar-name>
<connection-definition>
de.danet.an.workflow.rmsimpls.eisrms.aci.RmsConnectionFactory
</connection-definition>
<config-property name="PropertiesDirUrl" type="java.lang.String">
${jboss.server.config.url}
</config-property>
<config-property name="UsersPropertiesFile" type="java.lang.String">
wfdemopluto-users.properties
</config-property>
<config-property name="RolesPropertiesFile" type="java.lang.String">
wfdemopluto-roles.properties
</config-property>
<config-property name="GroupsPropertiesFile" type="java.lang.String">
wfdemopluto-groups.properties
</config-property>
</no-tx-connection-factory>
</connection-factories>
Figure 6.1. Sample resource adapter configuration for JBoss
At the first glance it might seem overkill to implement the file based resource management as a resource adapter using the JCA. But if you take a closer look, you'll find that even a read-only file database is best modelled as an EIS in the J2EE architecture. And it's the easiest way to push the configuration options to your application server's management interface.
The most likely found, standard based resource management facility in an organization is an LDAP server. The WfMOpen distribution therefore includes an implementation of an LDAP based resource adapter for the resource management service.
All information required to access the LDAP server is made known to the resource adapter in its configuration. The properties to specify for deployment are:
JavaNamingFactoryInitial
The value of
java.naming.factory.initial
used when creating the initial context. Defaults to
com.sun.jndi.ldap.LdapCtxFactory.
JavaNamingSecurityAuthentication
The value of
java.naming.security.authentication
used when creating the initial context. Defaults to
simple.
JavaNamingProviderUrl
The value of
java.naming.provide.url used
when creating the initial context. Defaults to
ldap://localhost:389.
JavaNamingSecurityPrincipal
The value of
java.naming.security.principal
used when creating the initial context. Optional,
i.e. need not be specified if your LDAP server
allows anonymous access.
JavaNamingSecurityCredentials
The value of
java.naming.security.credentials
used when creating the initial context. Only used
when
JavaNamingSecurityPrincipal has
been set.
UserCtxDNThe DN of the directory entry that contains all known users.
UserFilter
A filter expression applied when listing all known
users in the directory specified by
UserCtxDN.
UserSearchAttribute
The user entry's attribute used when searching for
an entry that matches the principal name or a
criterion in member resource selection. Defaults to
uid.
UserResourceNameAttribute
The user entry's attribute used as resource display
name. Defaults to cn.
UserMemberKeyAttributeWhen searching for users that are members of groups or roles, an attribute of the groups' or roles' entries is by default compared to the user entry's DN. If, however, a user member key attribute is specified, the value of this attribute is read from the user entry, and this value is used for comparision instead of the user entry's DN.
GroupCtxDNThe DN of the directory entry that contains all known groups.
GroupFilter
A filter expression applied when listing all known
groups in the directory specified by
GroupCtxDN.
GroupSearchAttribute
The group entry's attribute used when searching for
an entry that matches a criterion in group resource
selection. Defaults to cn.
GroupResourceNameAttribute
The group entry's attribute used as resource display
name. Defaults to cn.
GroupMemberAttributeWhen searching for users that are members of groups, either the user entry's DN or the value of an attribute from the user entry (see above) is compared to an attribute of all role entries. The role attribute used is specified with this property.
RoleCtxDNThe DN of the directory entry that contains all known roles.
RoleFilter
A filter expression applied when listing all known
roles in the directory specified by
UserCtxDN.
RoleSearchAttribute
The role entry's attribute used when searching for
an entry that matches a criterion in role resource
selection. Defaults to cn.
RoleResourceNameAttribute
The role entry's attribute used as resource display
name. Defaults to cn.
RoleMemberAttributeWhen searching for users that are members of roles, either the user entry's DN or the value of an attribute from the user entry (see above) is compared to an attribute of all role entries. The role entry's attribute used is specified with this property.
A sample deployment configuration is shown below.
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- The properties based RMS resource adaptor service configuration -->
<connection-factories>
<no-tx-connection-factory>
<jndi-name>DefaultWfMOpenRmsRA</jndi-name>
<rar-name>
de.danet.an.plutoportalapp.ear#de.danet.an.workflow.ldaprmsra.rar
</rar-name>
<connection-definition>
de.danet.an.workflow.rmsimpls.eisrms.aci.RmsConnectionFactory
</connection-definition>
<config-property name="UserCtxDN" type="java.lang.String">
ou=People,dc=my-domain,dc=com
</config-property>
<config-property name="GroupCtxDN" type="java.lang.String">
ou=ResourceGroups,dc=my-domain,dc=com
</config-property>
<config-property name="RoleCtxDN" type="java.lang.String">
ou=ResourceRoles,dc=my-domain,dc=com
</config-property>
</no-tx-connection-factory>
</connection-factories>
Figure 6.2. Sample resource adapter configuration
Table of Contents
WfMOpen has full support for Wf-XML 2.0 as proposed by the WfMC to enable remote clients to access WfMOpen using SOAP requests. There are only minor deviations that are described below. This documentation is not meant to be a tutorial for Wf-XML. It is assumed that the reader is familiar with the ASAP and Wf-XML standards.
The implementation has successfully been tested with the generic ASAPClient that had been made available by the WfMC when Wf-XML was initially published. We do not know of any other means to test standard compliance and are therefore very interested in getting your feedback if you are testing interoperability.
The Wf-XML interface is packaged as a separate web application
component and distributed in
$DIST/lib/wfcore/de.danet.an.workflow.wfxml.war.
In order to use the interface, this WAR must be configured and
included in your EAR. The demo application (see Appendix C, The demo applications) includes the interface, i.e. you
can use the demo application to get acquainted with the
interface. The base url for accessing the interface in the demo is
http://localhost:8080/wfxml.
The central instance that is responsible to handle all requests is
the
de.danet.an.workflow.clients.wfxml.Servlet.
The different resource types are identified through the
ReceiverKey in the ASAP specific header. The
ResponseRequired tag is currently ignored. A
response is returned in any case.
The ReceiverKey is a URI with the following
structure
<schema:>//<authority>/<base_path>[?<query>]
The parts up to base_path describe the
deployment context of the servlet
(e.g. http://localhost:8080/wfxml).
All parts that are needed to identify a specific resource are
encoded in the query part of the URI as
key-value pairs. If the query is omitted, the request is assumed
to be directed at the Service Registry. The
following table shows how specific resources are addressed with
query parameters.
Table 7.1. Resource identification through the ReceiverKey
| Resource | ProcessId | PackageId | ProcessKey | ActivityKey |
|---|---|---|---|---|
| ServiceRegistry | n/a | n/a | n/a | n/a |
| Factory | required | required | n/a | n/a |
| Instance | required | required | required | n/a |
| Activity | required | required | required | required |
A request to e.g. the Factory for the process
proc that is described in package
pkg is made using the following
ReceiverKey (assuming the base path above):
http://localhost:8080/wfxml?Resource=Factory&PackageId=pkg&ProcessId=proc
Note that the values for PackageId and
ProcessId must be www-form-urlencoded
UTF-8 charset identifiers.
Of course, the usual procedure is to obtain resource references by
requesting listings from the parent resources, starting with the
Service Registry. In some cases, however, the
direct approach may be required (e.g. the above mentioned
ASAPClient starts at the Factory level,
i.e. you have to enter the resource reference to a factory).
The names of the states, as specified by ASAP, are enhanced to match the state names as they are used by WfMOpen. These extended state names have the ASAP prefix followed by a "." and the substate as it is returned by the OMG API.
ASAP specifies, that SetPropertiesRq calls need not
support the modification of all properties that are given, but at least
one to have any effect. Properties that are specified in the request,
but can not be altered are ignored without warning.
WfMOpen supports modification of the following properties:
ServiceRegistry
No modifications possible
Factory
No modifications possible
Instance
Description
ContextData
Activity
Name
Description
The implementation is based on the ASAP specification of OASIS and Wf-XML 2.0. It turned out that their schema definitions are erroneous. This implementation is shipped with adapted and partially corrected schema definitions.
The implementation of
NewDefinitionRq
differs from the specification. If the factory exists,
the process definition will be overwritten without warning.
It is also possible to create
multiple factories using a single request. Neither the ASAP
specification nor the Wf-XML specification consider the deletion
of processes. Using this approach it is possible to delete
processes within a package by simply overwriting the package
definition.
The implementation of
GetProperties
produces XML that fails validation, since the Wf-XML schema
definition is erroneous at this point. The ASAP schema defines groups for
Instance, Factory, and Observer. Wf-XML defines new groups for the
ServiceRegistry and the Activity resources, which are not
referenced by GetPropertiesRs, since this is specified
in the ASAP schema, and which does not know about any extensions.
As a consequence the new groups for the Service Registry and the
Activity resource must not be a part of a
GetPropertiesRs message.
The specification mentions that a
ListDefinitions may contain filters, i.e.
Name and Status. These
filters are missing in the schema definition and are not implemented.
However, filtering of factories might make sense, but more in terms
of the package and process ids, rather than the name, which might be
ambivalent.
SetDefinition
is not implemented. As a workaround,
NewDefinition
of
ServiceRegistry
can be used instead, see above.
TerminateRq
is not implemented, since the specification for this request in the
ASAP schema is missing. The Wf-XML specification refers to the ASAP
specification for this request, but it is not mentioned there.
As a workaround it is possible to use a ChangeStateRq
instead.
The
SubscribeRq
request allows to receive notification messages, if the process
state changes. The ASAP specification is not precise at this point.
The implemented behavior for these critical points is described
below.
Completion of a process includes also a state changes.
Observers will receive StateChangeRq
before a CompletedRq . ASAP provides
no hints, if the latter one is intended to be a
replacement for the first one.
The observer will be unsubscribed if the process
terminates. UnsubscribeRq requests
are ignored afterwards.
The implementation of
GetProperties
produces XML that fails validation caused by an error in the Wf-XML
schema as it is described for the Service Registry.
For
GetProperties
the field
DueDate
contains a timestamp that matches
Long.MAX_VALUE,
since this date is currently not available using the API.
This section provides an example of a C# client that is developed using Microsoft Visual Studio 2005[30].
WfMOpen's Wf-XML interface ships with a WSDL description that can be used
to generate code for a client. This WSDL is based on the WSDL that
is available from OASIS and fixes some problems that we have encountered.
Visual Studio supports code generation from
the supplied WSDL file with the wsdl
tool[31]. On the Visual Studio
Command Prompt enter
wsdl /language:cs /namespace:WfMOpen.WfXML /out:WfMOpenService.cs <base-url>/wfxml/wfxml?wsdl
Replace <base-url> with the URL of your
WfMOpen distribution.
This will create a file WfMOpenService.cs that has to added
to your Visual Studio solution. The error messages have their cause in the
erroneous ASAP and Wf-XML schema defintions and can be ignored.
Do not forget to add a reference to
System.Web.Services.
The following code will print a list of all declared processes on the
console:
using System;
using System.Collections.Generic;
using System.Text;
using WfMOpen.WfXML;
namespace WfXMLTestClient
{
class Program
{
static void Main(string[] args)
{
WfXmlServiceRegistry service = new WfXmlServiceRegistry();
Request req = new Request();
req.ReceiverKey = "<base-url>/wfxml/ServiceRegistry";
service.RequestValue = req;
DefinitionInfo[] definitions =
service.ListDefintions("<ListDefinitionRq/>");
for (int i = 0; i < definitions.Length; i++)
{
DefinitionInfo info = definitions[i];
Console.WriteLine(info.DefinitionKey);
}
}
}
}
[30] What would be the point in using Wf-XML to access WfMOpen when you have a Java client?
[31] Unfortunately, our WSDL file
does not work with the wsimport tool of Java 6 because
this tool enforces more XML schema restrictions. I.e. it behaves correctly,
but the problems cannot be fixes without major changes in the files
provided by OASIS and the WfMC (these files could really use some
cleanup).
Table of Contents
Besides the engine component, WfMOpen includes a GUI for common management tasks. The GUI is implemented as a portlet application, i.e. a set of JSR-168 compliant portlets. Portals and portlets are the state of the art (if not only) open component technology for Web based GUIs. Providing the management GUI as portlets allows you to easily integrate the portlets in your specific application GUI[32]. At the same time, a small footprint, stand-alone management GUI can be provided by using the minimal Pluto portal driver (see Apache Pluto site).
The process definition portlet enables an administrator to view the available process definitions and start new processes.
Also depicted in the figure above is the process definition upload. It allows the selection and upload of new process definitions.
The process portlet initially shows the list of processes managed by the workflow engine.
Clicking on a process name navigates to a detail view of the process. Use the bread-crumb navigation at the top of the portlet to go back to the process list ("All Processes").
Clicking on the small listing icon of either the process or an activity shows the events associated with the process or an activity.
A differently configured instance of the portlet can be displayed by selecting the "Assignments" item in the menu on the left. In this configuration, the portlet initially displays the list of known resources. Clicking on a resource name shows all assigned activities.
The portlet application is packaged as a self-contained WAR, i.e. it includes all libraries, resources etc. required to run the portlet in an JSR-168 compliant portal.
The only (obviously) missing libraries are the client libraries
of the application server that runs the workflow engine. These
libraries are required by the portlets to contact the workflow
engine. We assume that these libraries are made available in the
portal as a shared resource, not on a per-portlet application
base. If the runtime environment of the portal is an application
server (not just a servlet container), this is usually the case
by default. If the portal runs e.g. in Tomcat, the application
server's client libraries should be copied to
$CATALINA_HOME/shared/lib.
Unless the portal and the workflow engine run in the same
application server, the portlets need some information to lookup
the JNDI service of the application server that runs the
workflow engine. The preferred way to configure the JNDI server
is adding environment entries to the portlet application's
web.xml as described in newInstance().
The propagation of the security identity in call to the workflow
engine is left to the portlet container as described in the
"Java Portlet Specification" (JSR-168), section PLT.20.5
"Propagation of Security Identity in EJB Calls".
As distributed, the Jetspeed2 portal runs in the Tomcat servlet container environment (see Jetspeed2 Home Page). It therefore requires both the installation of the application server's client libraries and a configuration update to ensure security identity propagation. Both issues are described in the following section assuming that the workflow engine is deployed in JBoss.
After installation, start the portal once and shut it down again.
Now copy
$JBOSS_HOME/client/jbossall-client.jar
to $JETSPEED_HOME/shared/lib/. This makes
the JBoss client libraries availabe to all components run in
this Tomcat environment.
In
$JETSPEED_HOME/webapps/jetspeed/WEB-INF/classes/
create a new file login.conf with the
following contents:
Jetspeed {
org.apache.jetspeed.security.impl.DefaultLoginModule required;
org.jboss.security.ClientLoginModule required;
};
The line org.jboss.security.ClientLoginModule
required; (added with respect to the default
configuration[33]) causes the security credentials to be
propagated to invoke EJBs.
Table of Contents
XPDL TypeDeclarations are currently
not supported. As a workaround, simply use
<SchemaType/> as type
specification. Note that the implementation of type
declarations will only make the type information available
at the API. There will be no verification of complex
process relevant data set using the API against the type
declarations.
Currently only "text/javascipt", V1.5 and "text/ecmascript", 3rd Edition are supported as scripting languages.
The XForms tool does currently not support the XForms Repeat Module as described in the XForms Recommendation.
Table of Contents
This package defines the core domain of a workflow management
system. It is an adaption of the OMG "Workflow Management Facility
Sepcification, V1.2". We consider the interfaces and classes in
this package (together with the interfaces and classes in the
extended API
) to be useable as a
general Java workflow API, i.e. if there was a JSR for a Java
workflow API, we think the merger of these two packages would be a
good starting point.
We have tried to follow the original specification as close as possible. However, some conventions used by OMG do not fit in the Java environment and changes have been made accordingly.
The main differences are:
OMG separates words in identifiers using underscores. In the Java environment, words are delimited by using a capital letter.
The pattern for relationships has been replaced by
a single access method
RELNAMEs
that returns a collection (the plural "s" has been omitted
from the relation
history
of interface
WfExecutionObject
for gramatical reasons).
The OMG model introduces a class
WfEventAudit
.
While the collection of
WfEventAudit
s may be
considered the result of an audit, we think that individual
items are rather
WfAuditEvent
s. This conforms
better to the Java naming scheme where event classes end
with "...Event" and the corresponding listener interfaces
with "...Listener".
We have appended "
...Exception
" to the names
of the exceptions, as is usual in Java. Additionally,
we have put the exceptions in a separate sub-package to
avoid naming conflicts when all
omgcore
classes
are imported with a wildcard import.
There are no enumeration types in Java. While, in general, elements of enumeration types can simply be mapped to constant definitions, we have not followed this approach in all cases.
In the Java environment, the states and substates
of an execution object can conveniently be modelled as a
class hierarchy
. This provides type safe usage and allows to define some
convenient methods for handling state.
We have, however not changed the following:
The access method for attributes have not been renamed
getAttribute()
. The
getX()
/
setX(...)
pattern has been
introduced by JavaBeans for the configuration of component
properties, not as a general mechanism to access attributes.
The properties used in the OMG model are dynamic data
properties, not configuration options. Therefore, there is
no reason why they should follow the
getX()
/
setX(...)
pattern
The documentation of classes and methods in this package consists mostly of an abbreviated version of the description provided by OMG's "Workflow Management Facility Specification, V1.2". Unless otherwise stated, the description from the specification applies fully, i.e. you can use the specification to obtain a detailed understanding of the functionallity provided.
The following picture shows the complete model.

This exception is raised by an attempt to start a
WfProcess
that is already running.
public class de.danet.an.workflow.omgcore.AlreadyRunningException extends, de.danet.an.workflow.omgcore.InvalidControlOperationException
implements, java.io.Serializable {
// Public Constructorspublic AlreadyRunningException(String msg);
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.11, “Exception InvalidControlOperationException” -> Section A.1.2, “Exception AlreadyRunningException”
This exception is raised by an attempt to suspend a
WfExecutionObject
that is already suspended.
public class de.danet.an.workflow.omgcore.AlreadySuspendedException extends, de.danet.an.workflow.omgcore.InvalidControlOperationException
implements, java.io.Serializable {
// Public Constructorspublic AlreadySuspendedException(String msg);
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.11, “Exception InvalidControlOperationException” -> Section A.1.3, “Exception AlreadySuspendedException”
This exception is raised when a change of a
WfRequester
is requested, but cannot be fulfilled.
public class de.danet.an.workflow.omgcore.CannotChangeRequesterException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic CannotChangeRequesterException();
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.4, “Exception CannotChangeRequesterException”
This exception is raised by an attempt to complete execution of a
WfExecutionObject
when it cannot be completed yet.
public class de.danet.an.workflow.omgcore.CannotCompleteException extends, de.danet.an.workflow.omgcore.InvalidControlOperationException
implements, java.io.Serializable {
// Public Constructorspublic CannotCompleteException(String msg);
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.11, “Exception InvalidControlOperationException” -> Section A.1.5, “Exception CannotCompleteException”
This exception is raised by an operation on a
WfExecutionObject
that attempts to resume an object that is not in a proper condition.
public class de.danet.an.workflow.omgcore.CannotResumeException extends, de.danet.an.workflow.omgcore.InvalidControlOperationException
implements, java.io.Serializable {
// Public Constructorspublic CannotResumeException(String msg);
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.11, “Exception InvalidControlOperationException” -> Section A.1.6, “Exception CannotResumeException”
This exception is raised by an attempt to start a
WfProcess
that cannot be started yet.
public class de.danet.an.workflow.omgcore.CannotStartException extends, de.danet.an.workflow.omgcore.InvalidControlOperationException
implements, java.io.Serializable {
// Public Constructorspublic CannotStartException(String msg);
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.11, “Exception InvalidControlOperationException” -> Section A.1.7, “Exception CannotStartException”
This exception is raised by an operation on a
WfExecutionObject
that attempts to stop an object that is not in a proper condition.
public class de.danet.an.workflow.omgcore.CannotStopException extends, de.danet.an.workflow.omgcore.InvalidControlOperationException
implements, java.io.Serializable {
// Public Constructorspublic CannotStopException(String msg);
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.11, “Exception InvalidControlOperationException” -> Section A.1.8, “Exception CannotStopException”
This exception is raised by an operation on a
WfExecutionObject
that attempts to suspend an object that is not in the proper condidition.
public class de.danet.an.workflow.omgcore.CannotSuspendException extends, de.danet.an.workflow.omgcore.InvalidControlOperationException
implements, java.io.Serializable {
// Public Constructorspublic CannotSuspendException(String msg);
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.11, “Exception InvalidControlOperationException” -> Section A.1.9, “Exception CannotSuspendException”
This exception is raised by a request for event audit history of a
WfExecutionObject
when the history is not available.
For example because the implementation of the WFM facility does not support
recording of history for a specific execution object.
public class de.danet.an.workflow.omgcore.HistoryNotAvailableException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic HistoryNotAvailableException();
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.10, “Exception HistoryNotAvailableException”
This exception is raised by an operation on a
WfExecutionObject
that attempts to perform an invalid control operation on that object.
public abstract class de.danet.an.workflow.omgcore.InvalidControlOperationException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic InvalidControlOperationException(String msg);
}
Direct known subclasses
:
de.danet.an.workflow.omgcore.AlreadyRunningException
,
de.danet.an.workflow.omgcore.AlreadySuspendedException
,
de.danet.an.workflow.omgcore.CannotCompleteException
,
de.danet.an.workflow.omgcore.CannotResumeException
,
de.danet.an.workflow.omgcore.CannotStartException
,
de.danet.an.workflow.omgcore.CannotStopException
,
de.danet.an.workflow.omgcore.CannotSuspendException
,
de.danet.an.workflow.omgcore.NotRunningException
,
de.danet.an.workflow.omgcore.NotSuspendedException
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.11, “Exception InvalidControlOperationException”
This exception is raised by an attempt to update the context of the result
of a
WfExecutionObject
with data that does not match the signature of that object.
public class de.danet.an.workflow.omgcore.InvalidDataException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic InvalidDataException(String msg);
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.12, “Exception InvalidDataException”
This exception is raised by an attempt to signal a
WfAuditEvent
to a
WfRequester
that was not created by one of the
WfProcesses
associated with the
WfRequester
.
public class de.danet.an.workflow.omgcore.InvalidPerformerException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic InvalidPerformerException();
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.13, “Exception InvalidPerformerException”
This exception is raised by an attempt to assign an invalid priority to a
WfExecutionObject
.
public class de.danet.an.workflow.omgcore.InvalidPriorityException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic InvalidPriorityException(String msg);
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.14, “Exception InvalidPriorityException”
This exception is raised when a
WfRequester
is being identified that cannot be a "parent" of instances of the process
modell.
When a
WfRequester
is rejected, the invoking application might decide not to register a
WfRequester
with the
WfProcess
.
public class de.danet.an.workflow.omgcore.InvalidRequesterException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic InvalidRequesterException();
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.15, “Exception InvalidRequesterException”
This exception is raised by an attempt to assign or remove an invalid resource.
public class de.danet.an.workflow.omgcore.InvalidResourceException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic InvalidResourceException();
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.16, “Exception InvalidResourceException”
This exception is raised by an attempt to change the state of a
WfExecutionObject
to a state that is not defined for that object.
public class de.danet.an.workflow.omgcore.InvalidStateException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic InvalidStateException();public InvalidStateException(String msg);
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.17, “Exception InvalidStateException”
This exception is raised by an attempt to release a
WfResource
from an assignment it is not associated with.
public class de.danet.an.workflow.omgcore.NotAssignedException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic NotAssignedException();
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.18, “Exception NotAssignedException”
This exception is raised by an attempt to create a
WfProcess
using a
WfProcessMgr
that is disabled.
public class de.danet.an.workflow.omgcore.NotEnabledException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic NotEnabledException(String msg);
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.19, “Exception NotEnabledException”
This exception is raised by an operation on a
WfExecutionObject
that attempts to perform a control operation on an object that needs to be
in a running state, but is not.
public class de.danet.an.workflow.omgcore.NotRunningException extends, de.danet.an.workflow.omgcore.InvalidControlOperationException
implements, java.io.Serializable {
// Public Constructorspublic NotRunningException(String msg);
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.11, “Exception InvalidControlOperationException” -> Section A.1.20, “Exception NotRunningException”
This exception is raised by an operation on a
WfExecutionObject
that attempts to perform a control operation on an object that needs to be
in a suspended state, but is not.
public class de.danet.an.workflow.omgcore.NotSuspendedException extends, de.danet.an.workflow.omgcore.InvalidControlOperationException
implements, java.io.Serializable {
// Public Constructorspublic NotSuspendedException(String msg);
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.11, “Exception InvalidControlOperationException” -> Section A.1.21, “Exception NotSuspendedException”
ProcessData
represents context and result data of
a
WfExecutionObject
.
We assume that the names in a
NameValueSequence
as defined in the OMG sprecification have to be unique
(it is a reasonable assumption, although the OMG specification does not
state it explicitly). Therefore we simply map the
NameValueSequence
to a Map with keys of type
String
and values of type
Object
.
public interface de.danet.an.workflow.omgcore.ProcessData extends, java.util.Map {
}
Inheritance Path. Section A.1.22, “Interface ProcessData”
ProcessDataInfo
describes the structure of the process
data associated with a
WfExecutionObject
.
The OMG specification defines that the data type is specified by
its "IDL type represented by its string name". Porting this to Java
is a bit difficult as the equivalent to this would be to support
something like textual representations of Java types, i.e. Java
source code.
While this issue needs further investigation, we define the
following: Java primitive types are represented by the
corresponding classes (e.g. boolean values are represented by a map
entry with value
java.lang.Boolean.class
). Support of
complex types depends on the workflow engine used (some may support
any [serializable] Java object as process relevant data, some may
support only XML as serialized format), as does the way process
definitions define complex types (e.g. as XML Schema
Description).
In addition to the classes representing Java primitive forms, an implementation may therefore specify additional types to describe the type information of a process data item.
public interface de.danet.an.workflow.omgcore.ProcessDataInfo extends, java.util.Map {
}
Inheritance Path. Section A.1.23, “Interface ProcessDataInfo”
This exception is raised when a valid
WfRequester
is required by the process definition, but one is not supplied.
public class de.danet.an.workflow.omgcore.RequesterRequiredException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic RequesterRequiredException();
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.24, “Exception RequesterRequiredException”
This exception is raised when the requested result of a
WfExecutionObject
is not available (yet).
public class de.danet.an.workflow.omgcore.ResultNotAvailableException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic ResultNotAvailableException();
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.25, “Exception ResultNotAvailableException”
This exception is raised by the request for the source of a
WfAuditEvent
when the source is no longer available.
public class de.danet.an.workflow.omgcore.SourceNotAvailableException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic SourceNotAvailableException();
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.26, “Exception SourceNotAvailableException”
This exception is raised by an attempt to perform an invalid state
transistion of a
WfExecutionObject
.
public class de.danet.an.workflow.omgcore.TransitionNotAllowedException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic TransitionNotAllowedException(WfExecutionObject.State from,
WfExecutionObject.State to);public TransitionNotAllowedException(WfExecutionObject.State from,
WfExecutionObject.State to,
String msg);public TransitionNotAllowedException(String msg);
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.27, “Exception TransitionNotAllowedException”
public TransitionNotAllowedException(String msg);Parameters
msg
the given message.
Creates a new
TransitionNotAllowedException
with the
given message.
public TransitionNotAllowedException(WfExecutionObject.State from,
WfExecutionObject.State to);Parameters
from
current state
to
new state
Creates a new
TransitionNotAllowedException
.
This exception is raised when it is not allowed to update the process context.
public class de.danet.an.workflow.omgcore.UpdateNotAllowedException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic UpdateNotAllowedException(String msg);
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.1.28, “Exception UpdateNotAllowedException”
WfActivity
is a step in a process that is associated,
as part of an aggregation, with a single
WfProcess
.
It represents a request for work in the context of the containing
WfProcess
.
public interface de.danet.an.workflow.omgcore.WfActivity extends, de.danet.an.workflow.omgcore.WfExecutionObject, de.danet.an.workflow.omgcore.WfRequester {
// Public Methodspublic java.util.Collection assignments()
throws RemoteException;public void complete()
throws RemoteException, CannotCompleteException;public WfProcess container()
throws RemoteException;public boolean isMemberOfAssignments(WfAssignment member)
throws RemoteException;public ProcessData result()
throws RemoteException, ResultNotAvailableException;public void setResult(ProcessData result)
throws RemoteException, InvalidDataException;
}
Inheritance Path. Section A.1.29, “Interface WfActivity”
public java.util.Collection assignments()
throws RemoteException;Parameters
the collection of all the WfAssignment.
Exceptions
RemoteException
if a system-level error occurs.
Returns all the
WfAssignment
associated with a
WfActivity
.
public void complete()
throws RemoteException, CannotCompleteException;Exceptions
RemoteException
if a system-level error occurs.
CannotCompleteException
if the activity cannot be completed yet.
This method is used by an application to signal the completion
of an activity. Note that this does not necessarily imply that
the activity's state changes to
closed.completed
.
XPDL allows an activity to be implemented by several tools that
are executed in sequence. Only if
complete
is
called after the last tool has been started will the workflow
engine change the activity's state to
closed.completed
. Else the activity will remain in
the
open.running
state and the next tool will be started.
If
complete
is called while the activity's state has been
set to
open.not_running.suspended
the next tool will not be started until the activity is resumed.
The
extended API
provides methods for finding out which tool is currently being
executed.
public WfProcess container()
throws RemoteException;Parameters
the process.
Exceptions
RemoteException
if a system-level error occurs.
Returns the
WfProcess
that this activity is a part of.
public boolean isMemberOfAssignments(WfAssignment member)
throws RemoteException;Parameters
member
the assignment in question.
true if the assignment is among the assignments of this activity.
Exceptions
RemoteException
if a system-level error occurs.
Check if the given assignment is among the assignments of this activity.
public ProcessData result()
throws RemoteException, ResultNotAvailableException;Parameters
the process data as result
Exceptions
RemoteException
if a system-level error occurs.
ResultNotAvailableException
if accessing to the result of an activity is not supported or the result data are not available yet.
Returns the result produced by the realization of the work request represented by an activity.
public void setResult(ProcessData result)
throws RemoteException, InvalidDataException;Parameters
result
the result data.
Exceptions
RemoteException
if a system-level error occurs.
InvalidDataException
if the data do not match the signature of the activity or when an invalid attempt is made to update the results of an activity; lack of access rights might be one of those reasons.
Passes result data back to the workflow process. The data item names must be the names of formal IN or OUT parameters of the currently invoked tool or subflow.
A
WfAssignment
links
WfActivity
objects to
WfResource
objects. These links represent
real assignements for enacting the activity.
public interface de.danet.an.workflow.omgcore.WfAssignment extends, de.danet.an.workflow.omgcore.WfObject {
// Public Methodspublic WfActivity activity()
throws RemoteException;public WfResource assignee()
throws RemoteException;public void setAssignee(WfResource newValue)
throws RemoteException, InvalidResourceException;
}
Inheritance Path. Section A.1.30, “Interface WfAssignment”
public WfActivity activity()
throws RemoteException;Parameters
the associated activity.
Exceptions
RemoteException
if a system-level error occurs.
A
WfAssignment
is associated with one
WfActivity
; the association
is established when the assignment is created as part of
the resource selection process for the activity. This
method returns the associated activity.
public WfResource assignee()
throws RemoteException;Parameters
the associated resource.
Exceptions
RemoteException
if a system-level error occurs.
A
WfAssignment
is associated with one
WfResource
; the association
is established when the assignment is created as part of
the resource selection process for the activity. This
method returns the associated resource.
public void setAssignee(WfResource newValue)
throws RemoteException, InvalidResourceException;Parameters
newValue
the new resource.
Exceptions
InvalidResourceException
if an attempt is made to assign an invalid resource to the assignment.
RemoteException
if a system-level error occurs.
A
WfAssignment
is associated with one
WfResource
; the association
is established when the assignment is created as part of
the resource selection process for the activity; this method
can be used to reassign the assignment to another resource
at a later point in time.
A
WfAssignmentAuditEvent
provides an audit record of
assignment change information for either the status of an
assignment change for a
WfActivity
or when an exisiting
assignment is reassigned to another resource.
public interface de.danet.an.workflow.omgcore.WfAssignmentAuditEvent extends, de.danet.an.workflow.omgcore.WfAuditEvent {
// Public Methodspublic String newResourceKey();public String newResourceName();public String oldResourceKey();public String oldResourceName();
}
Inheritance Path. Section A.1.31, “Interface WfAssignmentAuditEvent”
public String newResourceKey();Parameters
the current value of the attribute.
Returns the current value of the attribute
newResourceKey
.
public String newResourceName();Parameters
the current value of the attribute.
Returns the current value of the attribute
newResourceName
.
A
WfAuditEvent
provides an audit record of workflow event
information.
It provides information on the source of the event and contains
specific event data. Workflow events include state changes, change of a
resource assignment, and data changes. Workflow events are persistent and
can be accessed navigating the history relationship of a
WfExecutionObject
.
Workflow audit event objects are not part of the persistent state of their source workflow object.
public interface de.danet.an.workflow.omgcore.WfAuditEvent {
// Public Static Fieldspublic static final String ACTIVITY_ASSIGNMENT_CHANGED = activityAssignmentChanged;public static final String ACTIVITY_CONTEXT_CHANGED = activityContextChanged;public static final String ACTIVITY_RESULT_CHANGED = activityResultChanged;public static final String ACTIVITY_STATE_CHANGED = activityStateChanged;public static final String PROCESS_CONTEXT_CHANGED = processContextChanged;public static final String PROCESS_CREATED = processCreated;public static final String PROCESS_STATE_CHANGED = processStateChanged;
// Public Methodspublic String activityKey();public String activityName();public String eventType();public String processKey();public String processMgrName();public String processMgrVersion();public String processName();public WfExecutionObject source()
throws SourceNotAvailableException;public java.util.Date timeStamp();
}
Inheritance Path. Section A.1.32, “Interface WfAuditEvent”
public static final String ACTIVITY_ASSIGNMENT_CHANGED = activityAssignmentChanged;An identifier for the event type "activityAssignmentChanged"
public static final String ACTIVITY_CONTEXT_CHANGED = activityContextChanged;An identifier for the event type "activityContextChanged"
public static final String ACTIVITY_RESULT_CHANGED = activityResultChanged;An identifier for the event type "activityResultChanged"
public static final String ACTIVITY_STATE_CHANGED = activityStateChanged;An identifier for the event type "activityStateChanged"
public static final String PROCESS_CONTEXT_CHANGED = processContextChanged;An identifier for the event type "processContextChanged"
public static final String PROCESS_CREATED = processCreated;An identifier for the event type "processCreated"
public static final String PROCESS_STATE_CHANGED = processStateChanged;An identifier for the event type "processStateChanged"
public String activityKey();Parameters
the current value of the attribute.
Returns the current value of the attribute
activityKey
.
public String activityName();Parameters
the current value of the attribute.
Returns the current value of the attribute
activityName
.
public String eventType();Parameters
the current value of the attribute.
Returns the current value of the attribute
eventType
.
public String processKey();Parameters
the current value of the attribute.
Returns the current value of the attribute
processKey
.
public String processMgrName();Parameters
the current value of the attribute.
Returns the current value of the attribute
processMgrName
.
public String processMgrVersion();Parameters
the current value of the attribute.
Returns the current value of the attribute
processMgrVersion
.
public String processName();Parameters
the current value of the attribute.
Returns the current value of the attribute
processName
.
public WfExecutionObject source()
throws SourceNotAvailableException;Parameters
the current value of the attribute.
Exceptions
SourceNotAvailableException
if the source is not available.
Returns the current value of the attribute
source
.
The source of the event is the
WfExceutionObject
associated to the event, i.e. that triggered the event.
The listener interface for receiving an event from a process.
public interface de.danet.an.workflow.omgcore.WfAuditHandler extends, java.util.EventListener {
// Public Methodspublic void receiveEvent(WfAuditEvent e)
throws InvalidPerformerException, RemoteException;
}
Inheritance Path. Section A.1.33, “Interface WfAuditHandler”
public void receiveEvent(WfAuditEvent e)
throws InvalidPerformerException, RemoteException;Parameters
e
the event.
Exceptions
InvalidPerformerException
thrown by the derived
WfRequester
if it receives an event from a
process that is not among its performers.
RemoteException
if a system-level error occurs.
Called by the workflow engine if an event occurs.
A
WfCreateProcessAuditEvent
provides an audit record
with information related to the creation of a process.
If the process is created as a sub-process of another process that is
synchronized with the main process via a
WfActivity
requester, information on the requester is recorded.
public interface de.danet.an.workflow.omgcore.WfCreateProcessAuditEvent extends, de.danet.an.workflow.omgcore.WfAuditEvent {
// Public Methodspublic String pActivityKey();public String pProcessKey();public String pProcessMgrName();public String pProcessMgrVersion();public String pProcessName();
}
Inheritance Path. Section A.1.34, “Interface WfCreateProcessAuditEvent”
public String pActivityKey();Parameters
the current value of the attribute.
Returns the current value of the attribute
pActivityKey
.
public String pProcessKey();Parameters
the current value of the attribute.
Returns the current value of the attribute
pProcessKey
.
public String pProcessMgrName();Parameters
the current value of the attribute.
Returns the current value of the attribute
pProcessMgrName
.
A
WfDataAuditEvent
provides an audit record of either
context
changes of a
WfExecutionObject
or result changes of a
WfActivity
.
public interface de.danet.an.workflow.omgcore.WfDataAuditEvent extends, de.danet.an.workflow.omgcore.WfAuditEvent {
// Public Methodspublic ProcessData newData();public ProcessData oldData();
}
Inheritance Path. Section A.1.35, “Interface WfDataAuditEvent”
WfExecutionObject
is an abstract base interface that defines
common attributes, states, and operations for
WfProcess
and
WfActivity
.
public interface de.danet.an.workflow.omgcore.WfExecutionObject extends, de.danet.an.workflow.omgcore.WfObject, java.io.Serializable {
// Public Methodspublic void abort()
throws RemoteException, CannotStopException, NotRunningException;public void changeState(String newState)
throws RemoteException, InvalidStateException, TransitionNotAllowedException;public String description()
throws RemoteException;public java.util.Collection history()
throws RemoteException, HistoryNotAvailableException;public WfExecutionObject.State howClosed()
throws RemoteException;public String key()
throws RemoteException;public java.util.Date lastStateTime()
throws RemoteException;public String name()
throws RemoteException;public int priority()
throws RemoteException;public ProcessData processContext()
throws RemoteException;public void resume()
throws RemoteException, CannotResumeException, NotRunningException, NotSuspendedException;public void setDescription(String newValue)
throws RemoteException;public void setName(String newValue)
throws RemoteException;public void setPriority(int newValue)
throws RemoteException, InvalidPriorityException, UpdateNotAllowedException;public void setProcessContext(ProcessData newValue)
throws RemoteException, InvalidDataException, UpdateNotAllowedException;public String state()
throws RemoteException;public void suspend()
throws RemoteException, CannotSuspendException, NotRunningException, AlreadySuspendedException;public void terminate()
throws RemoteException, CannotStopException, NotRunningException;public java.util.Collection validStates()
throws RemoteException;public WfExecutionObject.State whileOpen()
throws RemoteException;public WfExecutionObject.State whyNotRunning()
throws RemoteException;public WfExecutionObject.State workflowState()
throws RemoteException;
}
Inheritance Path. Section A.1.36, “Interface WfExecutionObject”
public void abort()
throws RemoteException, CannotStopException, NotRunningException;Exceptions
RemoteException
if a system-level error occurs.
CannotStopException
when the execution object cannot be aborted.
NotRunningException
when the object is not running.
Requests enactment of a suspended execution object to be aborted before its normal completion. The state is set to ClosedState.ABORTED.
public void changeState(String newState)
throws RemoteException, InvalidStateException, TransitionNotAllowedException;Parameters
newState
State to change to.
Exceptions
InvalidStateException
If
newState
is an invalid
state for the execution object.
TransitionNotAllowedException
If the transition from the current
state to
newState
is not allowed.
RemoteException
If a communication error occurred.
Updates the current state of the execution object. As a result the state of execution objects associated with this execution object might be updated, too.
public String description()
throws RemoteException;Parameters
a string value of the description.
Exceptions
RemoteException
If a communication error occurred.
Get the description of this
WfExecutionObject
.
public java.util.Collection history()
throws RemoteException, HistoryNotAvailableException;Parameters
the collection of all
WfAuditEvent
items.
Exceptions
RemoteException
if a system-level error occurs.
HistoryNotAvailableException
if any audit event item available.
Return all
WfAuditEvent
items associated with this
execution object.
public WfExecutionObject.State howClosed()
throws RemoteException;Parameters
the state as
State
object.
Exceptions
RemoteException
If a communication error occurred.
Returns the workflow state for closed execution objects.
public String key()
throws RemoteException;Parameters
string of the identifier.
Exceptions
RemoteException
If a communication error occurred.
Identifier of the execution object.
public java.util.Date lastStateTime()
throws RemoteException;Parameters
value of the time.
Exceptions
RemoteException
if a system-level error occurs.
Return the time the state of the WfExecutionObject was changed.
public String name()
throws RemoteException;Parameters
string of the descriptive identifier.
Exceptions
RemoteException
If a communication error occurred.
Return human readable, descriptive identifier of the execution object.
public int priority()
throws RemoteException;Parameters
the value of the priority.
Exceptions
RemoteException
if a system-level error occurs.
Return the priority of this
WfExecutionObject
.
public ProcessData processContext()
throws RemoteException;Parameters
the process relevant data that define the context of the execution object.
Exceptions
RemoteException
If a communication error occurred.
Return the context of this
WfExecutionObject
.
public void resume()
throws RemoteException, CannotResumeException, NotRunningException, NotSuspendedException;Exceptions
RemoteException
if a system-level error occurs.
CannotResumeException
when the execution object cannot be resumed. For example, resuming a WfActivity might not be allowed when the containing WfProcess is suspended.
NotRunningException
when the object is not running.
NotSuspendedException
when the object is not suspended.
Requests enactment of a suspended execution object to be resumed. The state is set to OpenState.Running (or a substate) from NotRunningState.SUSPENDED.
public void setDescription(String newValue)
throws RemoteException;Parameters
newValue
the description of this
WfExecutionObject
.
Exceptions
RemoteException
If a communication error occurred.
Set the description of this
WfExecutionObject
.
public void setName(String newValue)
throws RemoteException;Parameters
newValue
the description of this
WfExecutionObject
.
Exceptions
RemoteException
If a communication error occurred.
Set the name of this
WfExecutionObject
.
public void setPriority(int newValue)
throws RemoteException, InvalidPriorityException, UpdateNotAllowedException;Parameters
newValue
new priority to set
Exceptions
RemoteException
if a system-level error occurs.
InvalidPriorityException
when the specified priority is out of range.
UpdateNotAllowedException
when the priority cannot be updated.
Update the priority of this
WfExecutionObject
.
public void setProcessContext(ProcessData newValue)
throws RemoteException, InvalidDataException, UpdateNotAllowedException;Parameters
newValue
process relevant data that define the context of the execution object.
Exceptions
RemoteException
if a system-level error occurs.
InvalidDataException
when new process data does not match the
signature of this
WfExecutionObject
.
UpdateNotAllowedException
raised when the implementation of the WfM Facility or the specific workflow process does not allow an update of the context.
Set the context of this
WfExecutionObject
.
public String state()
throws RemoteException;Parameters
the current state.
Exceptions
RemoteException
If a communication error occurred.
Gets the current state of the object.
public void suspend()
throws RemoteException, CannotSuspendException, NotRunningException, AlreadySuspendedException;Exceptions
RemoteException
if a system-level error occurs.
CannotSuspendException
when the execution object cannot be
suspended. For example, an implementation of the WfM Facility might not
support suspension of a
WfActivity
.
NotRunningException
when the object is not running.
AlreadySuspendedException
when the object is already suspended.
Requests enactment of an execution object to be suspended. The state is set to NotRunningState.SUSPENDED (or one of its substates).
public void terminate()
throws RemoteException, CannotStopException, NotRunningException;Exceptions
RemoteException
if a system-level error occurs.
CannotStopException
when the execution object cannot be aborted.
NotRunningException
when the object is not running.
Requests enactment of an execution object to be terminated before its normal completion.
public java.util.Collection validStates()
throws RemoteException;Parameters
A collection of all the valid states.
Exceptions
RemoteException
If a communication error occurred.
Returns a list of all the valid states that can be reached from the current state.
public WfExecutionObject.State whileOpen()
throws RemoteException;Parameters
the state as
State
object.
Exceptions
RemoteException
if a system-level error occurs.
Returns the workflow state for open execution objects.
This class defines the sub-states of State.CLOSED of a
WfExecutionObject
as returned by
howClosedState()
.
public static class de.danet.an.workflow.omgcore.WfExecutionObject.ClosedState extends, de.danet.an.workflow.omgcore.WfExecutionObject.State
implements, java.io.Serializable {
// Public Static Fieldspublic static final WfExecutionObject.ClosedState ABORTED ;public static final WfExecutionObject.ClosedState COMPLETED ;public static final WfExecutionObject.ClosedState TERMINATED ;
// Protected Constructorsprotected WfExecutionObject.ClosedState(String text);
// Public Methodspublic WfExecutionObject.State getParent();public WfExecutionObject.State howClosedState();public WfExecutionObject.State whileOpenState();public WfExecutionObject.State whyNotRunningState();public WfExecutionObject.State workflowState();
}
Direct known subclasses
:
de.danet.an.workflow.api.Activity.ClosedCompletedState
Methods inherited from de.danet.an.workflow.omgcore.WfExecutionObject.State
:
fromString
,
getParent
,
howClosedState
,
isSameOrSubState
,
registerState
,
textRepresentation
,
toString
,
whileOpenState
,
whyNotRunningState
,
workflowState
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Fields inherited from de.danet.an.workflow.omgcore.WfExecutionObject.State
:
CLOSED
,
OPEN
Inheritance Path. java.lang.Object-> Section A.1.40, “Class WfExecutionObject.State” -> Section A.1.37, “Class WfExecutionObject.ClosedState”
protected WfExecutionObject.ClosedState(String text);Parameters
text
Textual representation of the state
Default constructor.
public static final WfExecutionObject.ClosedState ABORTED ;Indicates that the enactment of the execution object has been aborted before normal execution. No assumptions on the state of execution objects depending on this execution object are made when enters this state.
public static final WfExecutionObject.ClosedState COMPLETED ;When an execution object has finished its task in the overall workflow process it enters the completed state; it is assumed that all execution objects associated with that execution object are completed when it enters this state.
public static final WfExecutionObject.ClosedState TERMINATED ;Indicates that enactment of the execution object was stopped before normal completion. It is assumed that all execution objects depending on this execution object (i.e., WfActivities contained in a WfProcess or a WfProcess implementing a WfActivity) are either completed or are terminated when it enters this state.
public WfExecutionObject.State getParent();Parameters
parent in the state hierachy
Returns the parent in the state hierachy if all states
defined in this class or
null
, if this states
are at the top level of the hierachy.
public WfExecutionObject.State howClosedState();Parameters
the sub-state of closed state
Returns the workflow substate for closed execution objects.
public WfExecutionObject.State whileOpenState();Parameters
the sub-state of open state
Returns the workflow substate for open execution objects.
This class defines the sub-states of OpenState.NOT_RUNNING of a
WfExecutionObject
as returned by
whyNotRunningState()
.
public static class de.danet.an.workflow.omgcore.WfExecutionObject.NotRunningState extends, de.danet.an.workflow.omgcore.WfExecutionObject.OpenState
implements, java.io.Serializable {
// Public Static Fieldspublic static final WfExecutionObject.NotRunningState NOT_STARTED ;public static final WfExecutionObject.NotRunningState SUSPENDED ;
// Protected Constructorsprotected WfExecutionObject.NotRunningState(String text);
// Public Methodspublic WfExecutionObject.State getParent();public WfExecutionObject.State howClosedState();public WfExecutionObject.State whileOpenState();public WfExecutionObject.State whyNotRunningState();public WfExecutionObject.State workflowState();
}
Methods inherited from de.danet.an.workflow.omgcore.WfExecutionObject.OpenState
:
getParent
,
howClosedState
,
whileOpenState
,
whyNotRunningState
,
workflowState
Methods inherited from de.danet.an.workflow.omgcore.WfExecutionObject.State
:
fromString
,
isSameOrSubState
,
registerState
,
textRepresentation
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Fields inherited from de.danet.an.workflow.omgcore.WfExecutionObject.OpenState
:
NOT_RUNNING
,
RUNNING
Fields inherited from de.danet.an.workflow.omgcore.WfExecutionObject.State
:
CLOSED
,
OPEN
Inheritance Path. java.lang.Object-> Section A.1.40, “Class WfExecutionObject.State” -> Section A.1.39, “Class WfExecutionObject.OpenState” -> Section A.1.38, “Class WfExecutionObject.NotRunningState”
protected WfExecutionObject.NotRunningState(String text);Parameters
text
Textual representation of the state
Default constructor.
public static final WfExecutionObject.NotRunningState NOT_STARTED ;Provides a state after creation where the object is active and ready to be initialized and started.
public static final WfExecutionObject.NotRunningState SUSPENDED ;Provides a state to temporarily pause the execution of the object. When an execution object is suspended, no execution objects depending on this object may be started.
public WfExecutionObject.State getParent();Parameters
parent in the state hierachy
Returns the parent in the state hierachy if all states
defined in this class or
null
, if this states
are at the top level of the hierachy.
public WfExecutionObject.State howClosedState();Parameters
the sub-state of closed state
Returns the workflow substate for closed execution objects.
public WfExecutionObject.State whileOpenState();Parameters
the sub-state of open state
Returns the workflow substate for open execution objects.
This class defines the sub-states of State.OPEN of a
WfExecutionObject
as returned by
whileOpenState()
.
public static class de.danet.an.workflow.omgcore.WfExecutionObject.OpenState extends, de.danet.an.workflow.omgcore.WfExecutionObject.State
implements, java.io.Serializable {
// Public Static Fieldspublic static final WfExecutionObject.OpenState NOT_RUNNING ;public static final WfExecutionObject.OpenState RUNNING ;
// Protected Constructorsprotected WfExecutionObject.OpenState(String text);
// Public Methodspublic WfExecutionObject.State getParent();public WfExecutionObject.State howClosedState();public WfExecutionObject.State whileOpenState();public WfExecutionObject.State whyNotRunningState();public WfExecutionObject.State workflowState();
}
Direct known subclasses
:
de.danet.an.workflow.omgcore.WfExecutionObject.NotRunningState
Methods inherited from de.danet.an.workflow.omgcore.WfExecutionObject.State
:
fromString
,
getParent
,
howClosedState
,
isSameOrSubState
,
registerState
,
textRepresentation
,
toString
,
whileOpenState
,
whyNotRunningState
,
workflowState
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Fields inherited from de.danet.an.workflow.omgcore.WfExecutionObject.State
:
CLOSED
,
OPEN
Inheritance Path. java.lang.Object-> Section A.1.40, “Class WfExecutionObject.State” -> Section A.1.39, “Class WfExecutionObject.OpenState”
protected WfExecutionObject.OpenState(String text);Parameters
text
Textual representation of the state
Default constructor.
public static final WfExecutionObject.OpenState NOT_RUNNING ;Object is active and quiescent, but ready to execute.
public static final WfExecutionObject.OpenState RUNNING ;The object is active and executing in the workflow.
public WfExecutionObject.State getParent();Parameters
parent in the state hierachy
Returns the parent in the state hierachy if all states
defined in this class or
null
, if this states
are at the top level of the hierachy.
public WfExecutionObject.State howClosedState();Parameters
the sub-state of closed state
Returns the workflow substate for closed execution objects.
public WfExecutionObject.State whileOpenState();Parameters
the sub-state of open state
Returns the workflow substate for open execution objects.
This class defines the top-hierachy possible states of a
WfExecutionObject
as returned
by
workflowState()
.
public static class de.danet.an.workflow.omgcore.WfExecutionObject.Stateimplements, java.io.Serializable {
// Public Static Fieldspublic static final WfExecutionObject.State CLOSED ;public static final WfExecutionObject.State OPEN ;
// Protected Constructorsprotected WfExecutionObject.State(String text);
// Public Static Methodspublic static WfExecutionObject.State fromString(String text)
throws InvalidStateException;
// Public Methodspublic WfExecutionObject.State getParent();public WfExecutionObject.State howClosedState();public boolean isSameOrSubState(WfExecutionObject.State s);public String toString();public WfExecutionObject.State whileOpenState();public WfExecutionObject.State whyNotRunningState();public WfExecutionObject.State workflowState();
// Protected Methodsprotected static void registerState(WfExecutionObject.State state);protected final String textRepresentation();
}
Direct known subclasses
:
de.danet.an.workflow.omgcore.WfExecutionObject.ClosedState
,
de.danet.an.workflow.omgcore.WfExecutionObject.OpenState
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
toString
,
wait
Inheritance Path. java.lang.Object-> Section A.1.40, “Class WfExecutionObject.State”
protected WfExecutionObject.State(String text);Parameters
text
Textual representation of the state
Default constructor.
public static final WfExecutionObject.State CLOSED ;Reflects that the object is finished and inactive.
public static final WfExecutionObject.State OPEN ;To reflect that the object is active and not finished.
public static WfExecutionObject.State fromString(String text)
throws InvalidStateException;Parameters
text
state name to search
state object
Exceptions
InvalidStateException
if
text
is not a valid
state name.
Get a state by name.
public WfExecutionObject.State getParent();Parameters
parent in the state hierachy
Returns the parent in the state hierachy if all states
defined in this class or
null
, if this states
are at the top level of the hierachy.
public WfExecutionObject.State howClosedState();Parameters
the state as
State
object.
Returns the workflow substate for closed execution objects.
public boolean isSameOrSubState(WfExecutionObject.State s);Parameters
s
State to compare
true
if same or sub-state
false
else.
Checks if this state is the same state as the given state or a substate of the given state.
protected static void registerState(WfExecutionObject.State state);Parameters
state
the
State
to be registered.
Register state for
fromString
evaluation.
Additionally introduced sub-states must call this method
during their initialization if the textual representation
is to be recognized in the
fromString
method.
It is up to the implementor of a derived state to assure
that the sub-state is initialized before the from String
method is called.
protected final String textRepresentation();Parameters
the textual representation
Return the textual representation of the state.
public String toString();Parameters
string representation of the state.
Returns the string representation of the state.
public WfExecutionObject.State whileOpenState();Parameters
the state as
State
object.
Returns the workflow substate for open execution objects.
A tagging interface that all omgcore interfaces must extend.
public interface de.danet.an.workflow.omgcore.WfObject {
}
Inheritance Path. Section A.1.41, “Interface WfObject”
WfProcess
is the performer of a workflow request. All
workflow objects that perform work implement this interface. This
interface allows work to proceed asynchronously while being monitored
and controlled.
public interface de.danet.an.workflow.omgcore.WfProcess extends, de.danet.an.workflow.omgcore.WfExecutionObject {
// Public Methodspublic java.util.Collection activitiesInState(String state)
throws RemoteException, InvalidStateException;public WfProcessMgr manager()
throws RemoteException;public WfRequester requester()
throws RemoteException;public ProcessData result()
throws RemoteException, ResultNotAvailableException;public void setRequester(WfRequester requester)
throws RemoteException, CannotChangeRequesterException;public void start()
throws RemoteException, CannotStartException, AlreadyRunningException;public java.util.Collection steps()
throws RemoteException;
}
Inheritance Path. Section A.1.42, “Interface WfProcess”
public java.util.Collection activitiesInState(String state)
throws RemoteException, InvalidStateException;Parameters
state
the given state.
the collection of all WfActivities.
Exceptions
RemoteException
if a system-level error occurs.
InvalidStateException
if an invalid state has been specified.
Return all
WfActivity
objects that are in a certain state.
public WfProcessMgr manager()
throws RemoteException;Parameters
the associated WfProcessMgr.
Exceptions
RemoteException
if a system-level error occurs.
Returns the
WfProcessMgr
associated with the
WfProcess
.
public WfRequester requester()
throws RemoteException;Parameters
the associated
WfRequester
.
Exceptions
RemoteException
if a system-level error occurs.
Returns the
WfRequester
associated with this
WfProcess
.
public ProcessData result()
throws RemoteException, ResultNotAvailableException;Parameters
process data representing intermediate result.
Exceptions
RemoteException
if a system-level error occurs.
ResultNotAvailableException
when the result cannot be obtained yet.
Returns the result produced by the WfProcess. In general the result is undefined until the process completes, but some processes may produce intermediate results.
public void setRequester(WfRequester requester)
throws RemoteException, CannotChangeRequesterException;Parameters
requester
new WfRequester.
Exceptions
RemoteException
if a system-level error occurs.
CannotChangeRequesterException
if ressignment of the process is not supported.
Reassigns the
WfProcess
to another
WfRequester
.
public void start()
throws RemoteException, CannotStartException, AlreadyRunningException;Exceptions
RemoteException
if a system-level error occurs.
CannotStartException
when the process cannot be started (e.g., because it is not properly initialized).
AlreadyRunningException
when the process has already been started.
Initiate enactment of a WfProcess.
A
WfProcessMgr
represents a template for a specific
workflow process; it is used to create instances of a workflow
process. Logically it is the factory and locator for
WfProcess
instances.
public interface de.danet.an.workflow.omgcore.WfProcessMgr extends, de.danet.an.workflow.omgcore.WfObject {
// Public Static Fieldspublic static final int DISABLED = 0;public static final int ENABLED = 1;
// Public Methodspublic String category()
throws RemoteException;public ProcessDataInfo contextSignature()
throws RemoteException;public WfProcess createProcess(WfRequester requester)
throws RemoteException, NotEnabledException, InvalidRequesterException, RequesterRequiredException;public String description()
throws RemoteException;public String name()
throws RemoteException;public int processMgrState()
throws RemoteException;public java.util.Collection processes()
throws RemoteException;public ProcessDataInfo resultSignature()
throws RemoteException;public void setProcessMgrState(int newState)
throws RemoteException, TransitionNotAllowedException;public String version()
throws RemoteException;
}
Inheritance Path. Section A.1.43, “Interface WfProcessMgr”
public String category()
throws RemoteException;Parameters
the string of category.
Exceptions
RemoteException
if a system-level error occurs.
Return the category of a process manager used for classification of process types. It is set when the process manager is initialized and cannot be modified.
public ProcessDataInfo contextSignature()
throws RemoteException;Parameters
the process meta information.
Exceptions
RemoteException
if a system-level error occurs.
Returns the meta information that defines how to set the context of an instance.
public WfProcess createProcess(WfRequester requester)
throws RemoteException, NotEnabledException, InvalidRequesterException, RequesterRequiredException;Parameters
requester
the requester to create process.
the created process.
Exceptions
RemoteException
if a system-level error occurs.
NotEnabledException
when the process manager is disabled.
InvalidRequesterException
when the process definition requires
a
WfRequester
and an invalid
WfRequester
is
supplied in the parameter.
RequesterRequiredException
when a
WfRequester
is
being identified that cannot be a parent of instances of the process.
Create instances of a process and link its requester.
public String description()
throws RemoteException;Parameters
the description.
Exceptions
RemoteException
if a system-level error occurs.
Returns the description of the process manager.
public String name()
throws RemoteException;Parameters
the name.
Exceptions
RemoteException
if a system-level error occurs.
Returns the name of the process manager.
public java.util.Collection processes()
throws RemoteException;Parameters
a Collection object of
WfProcess
.
Exceptions
RemoteException
if a system-level error occurs.
Returns a collection with
WfProcess
objects from this
process manager.
public int processMgrState()
throws RemoteException;Parameters
WfProcessMgr.ENABLED if creation of workflow processes is enabled, otherwise WfProcessMgr.DISABLED.
Exceptions
RemoteException
if a system-level error occurs.
Returns the state of the
WfProcessMgr
.
public ProcessDataInfo resultSignature()
throws RemoteException;Parameters
the process meta information.
Exceptions
RemoteException
if a system-level error occurs.
Returns the meta information that specifies how instances will return results.
WfRequester
is the interface that has a direct concern
with the execution and results of a workflow process. It represents
the request for some work to be done. Its performer, a
WfProcess
is
expected to handle its request and communicate significant status
changes; in particular to inform the requester when it has
completed performing the request work.
The support of
WfRequester
s in a workflow engine
implementation is complicated because the
receiveEvent
method
reverses the client server relationship and because an object from
the application space must be stored by the server.
Implementations of
WfRequester
are therefore subject
to the following restrictions:
The implementation must implement <code>java.io.Serializable</code>. Make sure not to use any attributes that are not serializable.
In order for deserialization to work, the implementation's class file must be in the classpath of the application server.
The implementation must provide proper <code>equals</code> and <code>hashCode</code> methods.
Most applications will simply use the requester provided as
DefaultRequester
.
public interface de.danet.an.workflow.omgcore.WfRequester extends, de.danet.an.workflow.omgcore.WfObject, de.danet.an.workflow.omgcore.WfAuditHandler {
// Public Methodspublic boolean isMemberOfPerformers(WfProcess member)
throws RemoteException;public java.util.Collection performers()
throws RemoteException;
}
Inheritance Path. Section A.1.44, “Interface WfRequester”
public boolean isMemberOfPerformers(WfProcess member)
throws RemoteException;Parameters
member
the process in question.
true
if the
process
is among
the performers of this requester.
Exceptions
RemoteException
if a system-level error occurs.
Check if the given process is among the performers of this requester.
WfResource
is an abstraction that represents a person or
thing that will potentially accept an assignment to an activity.
public interface de.danet.an.workflow.omgcore.WfResource extends, de.danet.an.workflow.omgcore.WfObject {
// Public Methodspublic boolean isMemberOfWorkItems(WfAssignment member)
throws RemoteException;public void release(WfAssignment fromAssignment,
String releaseInfo)
throws RemoteException, NotAssignedException;public String resourceKey()
throws RemoteException;public String resourceName()
throws RemoteException;public java.util.Collection workItems()
throws RemoteException;
}
Inheritance Path. Section A.1.45, “Interface WfResource”
public boolean isMemberOfWorkItems(WfAssignment member)
throws RemoteException;Parameters
member
the given
WfAssignment
.
true
if the association exists.
Exceptions
RemoteException
if a system-level error occurs.
Checks if a given
WfAssignment
is
associated with this resource.
public void release(WfAssignment fromAssignment,
String releaseInfo)
throws RemoteException, NotAssignedException;Parameters
fromAssignment
the specific assignment.
releaseInfo
specifies additional information on the reason for realizing the resource as input.
Exceptions
NotAssignedException
if the resource is not associated with the given assignment.
RemoteException
if a system-level error occurs.
Signals to the resource that it is no longer needed for a specific assignment. It is assumed that this operation is invoked when an assignment is deleted or when an assignment is reassigned to another resource.
(The description from the OMG specification is a bit unclear
about the nature of this method. Is it used to
signal
the release, or does it
cause
the release, i.e. does
it update the storage of assignments. Due to the fact that this
method throws
NotAssignedException
, which is
possible only if this method interfaces with the assignment
storage, we have opted for the latter.)
public String resourceKey()
throws RemoteException;Parameters
the resource key.
Exceptions
RemoteException
if a system-level error occurs.
Returns the resource key. The resource key identifies a resource within a given business domain. It is assumed that resources are defined in the same business domain as the workflow process they are associated with.
The key is set when the object is initialized; modification of the key can be done in the context of a resource management facility.
public String resourceName()
throws RemoteException;Parameters
the name of the resource.
Exceptions
RemoteException
if a system-level error occurs.
Returns a human readable, descriptive name of the resource.
public java.util.Collection workItems()
throws RemoteException;Parameters
the associated
WfAssignments
s.
Exceptions
RemoteException
if a system-level error occurs.
This method returns the
WfAssignments
s
associated with a resource.
A
WfStateAuditEvent
provides an audit record of
information for a
WfExecutionObject
's state change.
public interface de.danet.an.workflow.omgcore.WfStateAuditEvent extends, de.danet.an.workflow.omgcore.WfAuditEvent {
// Public Methodspublic String newState();public String oldState();
}
Inheritance Path. Section A.1.46, “Interface WfStateAuditEvent”
This package defines the the workflow API provided by Danet's
workflow component. The API extends the
core API
derived from
the OMG "Workflow Management Facility Sepcification, V1.2". We
consider the interfaces and classes in this package (together with
the interfaces and classes in the core API) to be useable as a
general Java workflow API, i.e. if there was a JSR for a Java
workflow API, we think the merger of these two packages would be a
good starting point.
Trying to implement workflow clients using the OMG interface, we found that it lacks some functions that are either absolutely necessary or nice to have. For some OMG interfaces we have therefore defined a corresponding interface that extends the OMG base interface.
We have also added some interface for areas that the OMG specification has purposely omitted from its scope (e.g. access to process definitions).
Finally, the OMG specification has left it open how to access the
root objects of type
WfProcessMgr
. We have therefore defined a
WorkflowService
and its corresponding
factory
that
provides this access (among some other useful function).
Interface
Activity
adds some functions to the
OMG activity
.
public interface de.danet.an.workflow.api.Activity extends, de.danet.an.workflow.api.ExecutionObject, de.danet.an.workflow.omgcore.WfActivity {
// Public Methodspublic void abandon(String exceptionName)
throws RemoteException, TransitionNotAllowedException;public Activity.Info activityInfo()
throws RemoteException;public String blockActivity()
throws RemoteException;public void changeAssignment(de.danet.an.workflow.omgcore.WfResource oldResource,
de.danet.an.workflow.omgcore.WfResource newResource)
throws RemoteException, InvalidResourceException, AlreadyAssignedException, NotAssignedException;public boolean choose()
throws RemoteException, TransitionNotAllowedException;public Activity.DeadlineInfo[] deadlines()
throws RemoteException;public Activity.Implementation executor()
throws RemoteException;public de.danet.an.workflow.omgcore.WfResource getResource(de.danet.an.workflow.omgcore.WfAssignment asnmnt)
throws RemoteException;public String[] handledExceptions()
throws RemoteException;public Activity.Implementation[] implementation()
throws RemoteException;public Activity.JoinAndSplitMode joinMode()
throws RemoteException;public java.util.List nextActivities()
throws RemoteException;public String performer()
throws RemoteException;public void removeAssignment(de.danet.an.workflow.omgcore.WfResource resource)
throws RemoteException, InvalidResourceException, NotAssignedException;public Activity.JoinAndSplitMode splitMode()
throws RemoteException;public ActivityUniqueKey uniqueKey()
throws RemoteException;
}
Inheritance Path. Section A.2.2, “Interface Activity”
public void abandon(String exceptionName)
throws RemoteException, TransitionNotAllowedException;Parameters
exceptionName
the name of the exception
Exceptions
RemoteException
if a system-level error occurs
TransitionNotAllowedException
if the activity is not executing a tool
Force the completion of this activity, leaving it in state "closed.completed.abandoned". Does nothing if the activity is in state "closed" already or has not been started ("open.not_running.not_started").
An abandoned activity is considered to be completed under
exceptional circumstances. Therefore only transitions with
conditions of type
EXCEPTION
or
DEFAULTEXCEPTION
are considered when evaluating
the set of subsequent activities. The argument is the name of
the exception which may be used to distinguish different
exceptions in transition evaluation (see XPDL).
This method should be used with care. In general, exceptions have a different level of abstraction in a workflow process description than in Java programming. The author of a workflow process should not have to know about e.g. a "SAXException". But he may know what to do in case of a "ResultInvalid" exception (though this kind of problem should only arise during development anyway).
This method may only be called during tool execution. Note that calling this method does not terminate tool execution, i.e. the method will return. A tool agent should, however, not try to do anything with the activity any more after calling this method.
public Activity.Info activityInfo()
throws RemoteException;Parameters
the resulting
Activity.Info
value
Exceptions
RemoteException
if a system-level error occurs
This method returns all available information about the activity in a single operation.
public String blockActivity()
throws RemoteException;Parameters
an identification of the block activity that caused
this activity to be instantiated or
null
if this
activity was not instantiated as part of an activity set
Exceptions
RemoteException
if a system-level error occurs
Returns the key of the "parent" block activity. All activities implicitly created by a block activity share the same block activity key.
Note that there need not be an activity with the returned key, as an activity set is actually a template describing how to implement block activities. The information obtained can mainly be used to group all activities that have been instantiated as part of an activity set.
public void changeAssignment(de.danet.an.workflow.omgcore.WfResource oldResource,
de.danet.an.workflow.omgcore.WfResource newResource)
throws RemoteException, InvalidResourceException, AlreadyAssignedException, NotAssignedException;Parameters
oldResource
the resource that has its assignment removed
newResource
the resource to be assigned
Exceptions
RemoteException
if a system-level error occurs
InvalidResourceException
if the resource is invalid.
As the environment is a concurrent multi user environment,
WfResource
objects may become invalid.
AlreadyAssignedException
if the assignment already exists
NotAssignedException
if there is no assignment to the old resource
Change an assignment for enacting the activity. This method calls the corresponding method of the resource assignment service and creates the appropriate audit event.
This method is intended to be used by resource assignment
systems for implementing
WfAssignment.setAssignee
. Resource assignment
systems are responsible for implementing
WfAssignment
and could therefore perform the
reassignment directly; this would, however, leave the
generation of notifications unexecuted.
Clients should not use this method but rather call
WfAssignment.setAssignee
.
public boolean choose()
throws RemoteException, TransitionNotAllowedException;Parameters
true
if the activity could be made the
effectively chosen one
Exceptions
RemoteException
if a system-level error occurs
TransitionNotAllowedException
if the activity is neither running nor suspended
Makes this activity the chosen one in a set of activities started by an AND split with the "deferred choice" option set. All other activities in the set are reset to their initial state.
If the activity does not participate in a deferred choice,
this method does nothing and returns
true
.
public Activity.DeadlineInfo[] deadlines()
throws RemoteException;Parameters
the deadlines
Exceptions
RemoteException
if a system-level error occurs
Returns the deadlines defined for this activity.
public Activity.Implementation executor()
throws RemoteException;Parameters
current executor or
null
if no executor
running
Exceptions
RemoteException
if a system-level error occurs
Returns the current executor.
public de.danet.an.workflow.omgcore.WfResource getResource(de.danet.an.workflow.omgcore.WfAssignment asnmnt)
throws RemoteException;Parameters
asnmnt
the assignment
the resource
Exceptions
RemoteException
if a system-level error occurs.
1.3.4
Get the resource associated with an Assignment. The method calls
the corresponding method of the resource assignment service.
This method is intended to be used by resource assignment
systems for implementing
WfAssignment.assignee
.
Clients should not use this method but rather call
WfAssignment.assignee
.
public String[] handledExceptions()
throws RemoteException;Parameters
handled exceptions
Exceptions
RemoteException
if a system-level error occurs
Returns the names of the exceptions handled by this activity.
public Activity.Implementation[] implementation()
throws RemoteException;Parameters
an array of
Implementation
}s or
null
if no implementation is defined
Exceptions
RemoteException
if a system-level error occurs
Returns the implementation of the activity as
Implementation
s.
public Activity.JoinAndSplitMode joinMode()
throws RemoteException;Parameters
join mode
Exceptions
RemoteException
if a system-level error occurs
Returns the join mode.
public java.util.List nextActivities()
throws RemoteException;Parameters
the list of
Activity
objects.
Exceptions
RemoteException
if a system-level error occurs
Returns the list of activities that may follow this activity, i.e. to which transitions exist.
public String performer()
throws RemoteException;Parameters
performer as string
Exceptions
RemoteException
if a system-level error occurs
Returns the performer as string.
public void removeAssignment(de.danet.an.workflow.omgcore.WfResource resource)
throws RemoteException, InvalidResourceException, NotAssignedException;Parameters
resource
the resource whose assignment is to be canceled
Exceptions
RemoteException
if a system-level error occurs
InvalidResourceException
if the resource is invalid.
As the environment is a concurrent multi user environment,
WfResource
objects may become invalid.
NotAssignedException
if there is no such assignment
Removes an assignment for enacting the activity. This method calls the corresponding method of the resource assignment service and creates the appropriate audit event.
This method is intended to be used by resource management
systems for implementing
WfResource.release
.
Clients should not use this
method but rather call
WfResource.release
.
public Activity.JoinAndSplitMode splitMode()
throws RemoteException;Parameters
split mode
Exceptions
RemoteException
if a system-level error occurs
Returns the split mode.
public ActivityUniqueKey uniqueKey()
throws RemoteException;Parameters
value of uniqueKey
Exceptions
RemoteException
if a system-level error occurs
Return a unique key for the activity. (Note that the OMG
interface defines the key returned by the
key()
method as unique within the scope of the
containing process only.)
This class defines the sub-states of ClosedState.COMPLETED of a
WfExecutionObject
. These substates are an
extention of the predefined omg states.
public static class de.danet.an.workflow.api.Activity.ClosedCompletedState extends, de.danet.an.workflow.omgcore.WfExecutionObject.ClosedState
implements, java.io.Serializable {
// Public Static Fieldspublic static final Activity.ClosedCompletedState ABANDONED ;public static final Activity.ClosedCompletedState NORMAL ;
// Protected Constructorsprotected Activity.ClosedCompletedState(String text);
// Public Methodspublic de.danet.an.workflow.omgcore.WfExecutionObject.State getParent();public de.danet.an.workflow.omgcore.WfExecutionObject.State howClosedState();public de.danet.an.workflow.omgcore.WfExecutionObject.State whileOpenState();public de.danet.an.workflow.omgcore.WfExecutionObject.State whyNotRunningState();public de.danet.an.workflow.omgcore.WfExecutionObject.State workflowState();
}
Methods inherited from de.danet.an.workflow.omgcore.WfExecutionObject.ClosedState
:
getParent
,
howClosedState
,
whileOpenState
,
whyNotRunningState
,
workflowState
Methods inherited from de.danet.an.workflow.omgcore.WfExecutionObject.State
:
fromString
,
isSameOrSubState
,
registerState
,
textRepresentation
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Fields inherited from de.danet.an.workflow.omgcore.WfExecutionObject.ClosedState
:
ABORTED
,
COMPLETED
,
TERMINATED
Fields inherited from de.danet.an.workflow.omgcore.WfExecutionObject.State
:
CLOSED
,
OPEN
Inheritance Path. java.lang.Object-> Section A.1.40, “Class WfExecutionObject.State” -> Section A.1.37, “Class WfExecutionObject.ClosedState” -> Section A.2.3, “Class Activity.ClosedCompletedState”
protected Activity.ClosedCompletedState(String text);Parameters
text
Textual representation of the state
Default constructor.
public static final Activity.ClosedCompletedState ABANDONED ;Provides a state indicating that the activity was completed by an exception.
public static final Activity.ClosedCompletedState NORMAL ;Provides a state indicating that the activity was completed normally.
public de.danet.an.workflow.omgcore.WfExecutionObject.State getParent();Parameters
parent in the state hierachy
Returns the parent in the state hierachy if all states
defined in this class or
null
, if this states
are at the top level of the hierachy.
public de.danet.an.workflow.omgcore.WfExecutionObject.State howClosedState();Parameters
the closed state.
Returns the workflow substate for closed execution objects.
public de.danet.an.workflow.omgcore.WfExecutionObject.State whileOpenState();Parameters
the open state.
Returns the workflow substate for open execution objects.
Class
DeadlineInfo
describes all properties of a
deadline.
public static class de.danet.an.workflow.api.Activity.DeadlineInfoimplements, java.io.Serializable {
// Public Static Fieldspublic static final int ASYNCHR = 1;public static final int STATE_ACTIVE = 2;public static final int STATE_CANCELED = 3;public static final int STATE_INITIAL = 0;public static final int STATE_REACHED = 1;public static final int SYNCHR = 2;
// Public Constructorspublic Activity.DeadlineInfo(int executionMode,
String exceptionName,
String condition,
int state);
// Public Methodspublic String getCondition();public String getExceptionName();public int getExecutionMode();public int getState();
}
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
toString
,
wait
Inheritance Path. java.lang.Object-> Section A.2.4, “Class Activity.DeadlineInfo”
public Activity.DeadlineInfo(int executionMode,
String exceptionName,
String condition,
int state);Parameters
executionMode
the execution mode
exceptionName
the exception to be thrown
condition
the condition
state
the current state
Creates a new
DeadlineInfo
instance with the given
values.
public String getExceptionName();Parameters
value of ExceptionName.
Get the value of ExceptionName.
The super interface of possible activity implementation descriptions.
public static interface de.danet.an.workflow.api.Activity.Implementation extends, java.io.Serializable {
}
Inheritance Path. Section A.2.5, “Interface Activity.Implementation”
Class
Info
combines various informational
attributes about an activity in a single structure for
efficient retrieval.
public static class de.danet.an.workflow.api.Activity.Infoimplements, java.io.Serializable {
// Public Constructorspublic Activity.Info(ActivityUniqueKey key,
String actName,
String actDesc,
int actPrio,
java.util.Date actLastTime,
String procName,
String procDesc);
// Public Methodspublic String description();public java.util.Date lastStateTime();public String name();public int priority();public String processDescription();public String processName();public ActivityUniqueKey uniqueKey();
}
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
toString
,
wait
Inheritance Path. java.lang.Object-> Section A.2.6, “Class Activity.Info”
public Activity.Info(ActivityUniqueKey key,
String actName,
String actDesc,
int actPrio,
java.util.Date actLastTime,
String procName,
String procDesc);Parameters
key
the unique key.
actName
the activity name.
actDesc
the activity description.
actPrio
the priority of the activity.
actLastTime
the date of the last state change.
procName
the name of the containing process.
procDesc
the description of the containing process.
Creates a new
Info
instance with the given values.
public String description();Parameters
value of activityDescription.
Get the value of activityDescription.
public java.util.Date lastStateTime();Parameters
value of lastStateTime.
Get the value of lastStateTime.
public int priority();Parameters
value of activityPriority.
Get the value of activityPriority.
public String processDescription();Parameters
value of processDescription.
Get the value of processDescription.
This class defines the join and split modes for an activity.
public static class de.danet.an.workflow.api.Activity.JoinAndSplitModeimplements, java.io.Serializable {
// Public Static Fieldspublic static final Activity.JoinAndSplitMode AND ;public static final Activity.JoinAndSplitMode XOR ;
// Protected Constructorsprotected Activity.JoinAndSplitMode(String text);
// Public Static Methodspublic static Activity.JoinAndSplitMode fromString(String text)
throws IllegalArgumentException;
// Public Methodspublic final boolean isAND();public final boolean isXOR();public final String toString();
}
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
toString
,
wait
Inheritance Path. java.lang.Object-> Section A.2.7, “Class Activity.JoinAndSplitMode”
protected Activity.JoinAndSplitMode(String text);Parameters
text
textual representation of the mode.
Default constructor.
public static Activity.JoinAndSplitMode fromString(String text)
throws IllegalArgumentException;Parameters
text
mode name.
mode object
Exceptions
IllegalArgumentException
if
text
is not a valid
mode name.
Get the join/split mode by name.
public final boolean isAND();Parameters
true
if the mode is "AND".
Checks if the mode is "AND".
This class defines the values for start and finish mode for an
Activity
.
public static class de.danet.an.workflow.api.Activity.StartFinishModeimplements, java.io.Serializable {
// Public Static Fieldspublic static final Activity.StartFinishMode AUTOMATIC ;public static final Activity.StartFinishMode MANUAL ;
// Protected Constructorsprotected Activity.StartFinishMode(String text);
// Public Static Methodspublic static Activity.StartFinishMode fromString(String mode);
// Public Methodspublic String toString();
}
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
toString
,
wait
Inheritance Path. java.lang.Object-> Section A.2.8, “Class Activity.StartFinishMode”
protected Activity.StartFinishMode(String text);Parameters
text
textual representation of the activity mode.
Default constructor.
This interface describes the implementation of an activity by a sub flow.
public static interface de.danet.an.workflow.api.Activity.SubFlowImplementation extends, de.danet.an.workflow.api.Activity.Implementation {
// Public Static Fieldspublic static final int ASYNCHR = 1;public static final int SYNCHR = 2;
// Public Methodspublic int execution();public String packageId();public String processId();public String processKey();
}
Inheritance Path. Section A.2.9, “Interface Activity.SubFlowImplementation”
public String packageId();Parameters
value of package id.
Return the package id of the subflow. Can be used together
with the
processId
to
lookup the process definition using
ProcessDefinitionDirectory.lookupProcessDefinition
.
public String processId();Parameters
value of process id.
Return the process id of the subflow. Can be used together
with the
packageId
to
lookup the process definition using
ProcessDefinitionDirectory.lookupProcessDefinition
.
This interface describes the implementation of an activity by a tool.
public static interface de.danet.an.workflow.api.Activity.ToolImplementation extends, de.danet.an.workflow.api.Activity.Implementation {
// Public Methodspublic String description();public String id();
}
Inheritance Path. Section A.2.10, “Interface Activity.ToolImplementation”
public String description();Parameters
value of description.
Return the implementation description.
public String id();Parameters
value of id.
Return the tool id. The id can be mapped to a tool
definition by
ProcessDefinition.applicationById
.
This class implements a unique activity key. The OMG interface defines
the key returned by the
key()
method as unique within the scope of the containing
process only. The key of a process in turn is unique only among the
processes with a common process manager.
This class therefore combines the activity key, the process key and the process manager name to a unique activity key.
public class de.danet.an.workflow.api.ActivityUniqueKeyimplements, java.io.Serializable {
// Public Constructorspublic ActivityUniqueKey(de.danet.an.workflow.omgcore.WfActivity activity)
throws RemoteException;public ActivityUniqueKey(String managerName,
String processKey,
String activityKey);
// Public Methodspublic String activityKey();public boolean equals(Object other);public int hashCode();public String managerName();public String processKey();public String toString();
}
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
toString
,
wait
Inheritance Path. java.lang.Object-> Section A.2.11, “Class ActivityUniqueKey”
public ActivityUniqueKey(String managerName,
String processKey,
String activityKey);Parameters
managerName
the process manager name.
processKey
the process key.
activityKey
the activity key.
Creates an instance of
ActivityUniqueKey
from the given partial keys.
public ActivityUniqueKey(de.danet.an.workflow.omgcore.WfActivity activity)
throws RemoteException;Parameters
activity
the
WfActivity
.
Exceptions
RemoteException
if a system-level error occurs.
Creates an instance of
ActivityUniqueKey
for the given activity.
public boolean equals(Object other);Parameters
other
a
ActivityUniqueKey
value
true
if objects are equal.
Two
ActivityUniqueKey
s are equal, if all
attributes are equal.
public int hashCode();Parameters
the hash code.
Calculate a hash code for a
ActivityUniqueKey
object.
public String managerName();Parameters
the process manager name.
Return the process manager name.
This class provides ...
public class de.danet.an.workflow.api.AlreadyAssignedException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic AlreadyAssignedException();public AlreadyAssignedException(String message);
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.2.12, “Exception AlreadyAssignedException”
This interface defines methods to access the definition of an application that participates in a workflow process.
public interface de.danet.an.workflow.api.Application {
// Public Methodspublic String description();public String id();
}
Inheritance Path. Section A.2.13, “Interface Application”
This interface must be implemented by classes that can be run as batch.
public interface de.danet.an.workflow.api.Batch {
// Public Methodspublic Object execute(Batch.Context ctx)
throws InvocationTargetException;
}
Inheritance Path. Section A.2.14, “Interface Batch”
This interface specifies a simple contract between a batch and its execution environment.
public static interface de.danet.an.workflow.api.Batch.Context {
// Public Methodspublic boolean isRollbackOnly();
}
Inheritance Path. Section A.2.15, “Interface Batch.Context”
This exception is raised by an attempt to remove a
WfProcess
that is still in progress.
public class de.danet.an.workflow.api.CannotRemoveException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic CannotRemoveException(String msg);
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.2.16, “Exception CannotRemoveException”
This interface defines a named connection with a process that can be used to receive messages from activities and send messages to activities.
Note that messages sent from the workflow engine to clients on a channel may be lost when no client has opened the channel.
public interface de.danet.an.workflow.api.Channel extends, de.danet.an.workflow.omgcore.WfObject {
// Public Methodspublic String name()
throws RemoteException;public Process process()
throws InvalidKeyException, RemoteException;public java.util.Map receiveMessage()
throws RemoteException;public java.util.Map receiveMessage(long timeout)
throws RemoteException;public void sendMessage(java.util.Map msg)
throws InvalidKeyException, InvalidDataException, RemoteException;
}
Inheritance Path. Section A.2.17, “Interface Channel”
public String name()
throws RemoteException;Parameters
the name
Exceptions
RemoteException
if a system-level error occurs
Return the channel name.
public Process process()
throws InvalidKeyException, RemoteException;Parameters
the process
Exceptions
InvalidKeyException
if the process no longer exists
RemoteException
if a system-level error occurs
Return the process this channel belongs to.
public java.util.Map receiveMessage()
throws RemoteException;Parameters
the message or
null
if the process has
been closed or removed
Exceptions
RemoteException
if a system-level error occurs
Wait for the next message from the process on this channel. The
message consists of all
IN
or
INOUT
parameters of the sender tool, stored in the
Map
object by formal parameter name.
public java.util.Map receiveMessage(long timeout)
throws RemoteException;Parameters
timeout
the timeout value in milliseconds. A timeout of zero never expires.
the message or
null
if the process has
been closed or removed or the timeout expires
Exceptions
RemoteException
if a system-level error occurs
Wait for the next message from the process on this channel within
the specified timeout interval. The
message consists of all
IN
or
INOUT
parameters of the sender tool, stored in the
Map
object by formal parameter name.
public void sendMessage(java.util.Map msg)
throws InvalidKeyException, InvalidDataException, RemoteException;Parameters
msg
the message
Exceptions
InvalidKeyException
if the process no longer exists
InvalidDataException
if the message contains invalid data, i.e. entries that do not match the name of a formal parameter
RemoteException
if a system-level error occurs
Send a message on this channel to the process. The message will be received by an active or subsequently activated receiver tool listening on this channel. If two or more receiver tools listen on the same channel concurrently, the message delivery (only to one or to every receiver) is undefined.
The message sent is mapped to the formal
OUT
parameters of the receiver tool by matching the parameter names
with the data entry names in the message.
Interface
Configuration
.
Gives access to the configuration-methods.
public interface de.danet.an.workflow.api.Configuration extends, java.io.Serializable {
// Public Methodspublic String workflowEngineInstanceKey()
throws RemoteException;
}
Inheritance Path. Section A.2.18, “Interface Configuration”
public String workflowEngineInstanceKey()
throws RemoteException;Parameters
the unique instance key
Every workflow engine has a globally unique key. This key may be used in environments with several workflow engines to uniquely identify an instance. Note that this key should be bound to the data (state) of an engine, not to a deployment address. If an engine is moved to a different machine, but continues using the same data (i.e. all running processes remain the same etc.) then it should still provide the same instance key.
This class extends
HashMap
in order to provide a
default implementation of
ProcessData
.
public class de.danet.an.workflow.api.DefaultProcessData extends, java.util.HashMap
implements, de.danet.an.workflow.omgcore.ProcessData, java.io.Serializable {
// Public Constructorspublic DefaultProcessData();public DefaultProcessData(java.util.Map procData);
// Public Methodspublic String toString();
}
Methods inherited from java.util.HashMap
:
clear
,
clone
,
containsKey
,
containsValue
,
entrySet
,
get
,
isEmpty
,
keySet
,
put
,
putAll
,
remove
,
size
,
values
Methods inherited from java.util.AbstractMap
:
equals
,
hashCode
,
toString
Methods inherited from java.lang.Object
:
finalize
,
getClass
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.util.AbstractMap-> java.util.HashMap-> Section A.2.19, “Class DefaultProcessData”
This class provides an implementation of a
WfRequester
.
It class may be used directly if the events that are usually
delivered to a requester are of no interest.
If events are to be processed,
DefaultRequester
must
be subclassed with
receiveEvent
overridden with the event handling code.
As an alternative to subclassing, a handler may be passed to the
constructor
. Events will then be forwarded to the handler. This is
convenient in situation where the implementation of
WfAuditHandler
already exists and a
subclass would only do the forwarding. Note that the reference to the
handler is
transient
.
public class de.danet.an.workflow.api.DefaultRequesterimplements, de.danet.an.workflow.omgcore.WfRequester, java.io.Serializable {
// Public Constructorspublic DefaultRequester(WorkflowService wfs)
throws RemoteException;public DefaultRequester(WorkflowService wfs,
de.danet.an.workflow.omgcore.WfAuditHandler hdlr)
throws RemoteException;
// Protected Constructorsprotected DefaultRequester(WorkflowService wfs,
boolean register)
throws RemoteException;
// Public Methodspublic boolean equals(Object obj);public int hashCode();public boolean isMemberOfPerformers(de.danet.an.workflow.omgcore.WfProcess wfProcess)
throws RemoteException;public java.util.Collection performers()
throws RemoteException;public void receiveEvent(de.danet.an.workflow.omgcore.WfAuditEvent wfAuditEvent)
throws InvalidPerformerException, RemoteException;public String toString();
}
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
toString
,
wait
Inheritance Path. java.lang.Object-> Section A.2.20, “Class DefaultRequester”
public DefaultRequester(WorkflowService wfs)
throws RemoteException;Parameters
wfs
the workflow service.
Exceptions
RemoteException
if thrown during
requester registration
.
Creates a
DefaultRequester
for use with the given
workflow service. The created requester will not receive events
until registered with a
WorkflowService
.
protected DefaultRequester(WorkflowService wfs,
boolean register)
throws RemoteException;Parameters
wfs
the workflow service.
register
if
true
the requester will be
registered at the workflow service.
Exceptions
RemoteException
if thrown during
requester registration
.
Creates a
DefaultRequester
for use with the given
workflow service. The created requester is automatically
registered at the given
WorkflowService
.
public DefaultRequester(WorkflowService wfs,
de.danet.an.workflow.omgcore.WfAuditHandler hdlr)
throws RemoteException;Parameters
wfs
the workflow service.
hdlr
the event handler.
Exceptions
RemoteException
if thrown during
requester registration
.
Creates a
DefaultRequester
for use with the given
workflow service. The created requester will forward received events
to the given handler.
public boolean equals(Object obj);Parameters
obj
the other object.
true
if the objects are equal.
Indicates whether some other object is "equal to" this one.
public boolean isMemberOfPerformers(de.danet.an.workflow.omgcore.WfProcess wfProcess)
throws RemoteException;Specified by: Method isMemberOfPerformers in interface WfRequester
Parameters
member
the process in question.
true
if the
process
is among
the performers of this requester.
Exceptions
RemoteException
if a system-level error occurs.
Check if the given process is among the performers of this requester.
public java.util.Collection performers()
throws RemoteException;Specified by: Method performers in interface WfRequester
Parameters
A collection of associated performers.
Exceptions
RemoteException
if a system-level error occurs.
Return all performers associated with this requester.
An
EventSubscriber
represents a connection to the
workflow engine's event queue. From its creation with
WorkflowService.createEventSubscriber
until its
destruction with
WorkflowService.release
all events from the workflow
engine are delivered to the
EventSubscriber
.
EventSubscriber
s should be released using
WorkflowService.release
when
no longer needed as they may consume considerable resources.
public interface de.danet.an.workflow.api.EventSubscriber extends, de.danet.an.workflow.omgcore.WfObject {
// Public Methodspublic de.danet.an.workflow.omgcore.WfAuditEvent receive()
throws IOException;public de.danet.an.workflow.omgcore.WfAuditEvent receive(long timeout)
throws IOException;public de.danet.an.workflow.omgcore.WfAuditEvent receiveNoWait()
throws IOException;public void setEventHandler(de.danet.an.workflow.omgcore.WfAuditHandler handler)
throws IOException;
}
Inheritance Path. Section A.2.21, “Interface EventSubscriber”
public de.danet.an.workflow.omgcore.WfAuditEvent receive()
throws IOException;Parameters
the audit event
Exceptions
IOException
if an error occurs
Receives the next audit event. This method blocks until the next event is received.
public de.danet.an.workflow.omgcore.WfAuditEvent receive(long timeout)
throws IOException;Parameters
timeout
the timeout value (in milliseconds). If 0, the method blocks until a message is received.
the audit event or
null
if the timeout
expires
Exceptions
IOException
if an error occurs
Receives the next audit event that arrives within the specified timeout interval.
public de.danet.an.workflow.omgcore.WfAuditEvent receiveNoWait()
throws IOException;Parameters
the audit event or
null
if no event is
available
Exceptions
IOException
if an error occurs
Receives the next audit event if one is immediately available.
public void setEventHandler(de.danet.an.workflow.omgcore.WfAuditHandler handler)
throws IOException;Parameters
handler
the event handler
Exceptions
IOException
if an error occurs
Sets a handler for received events that is automatically
invoked. If a handler has been set, the
receive
methods may not be called.
Interface
ExecutionObject
extends the
OMG execution
object
with additional methods that allow the type-safe
state class
to be used to query and set state. The OMG API provides string
based methods only to enable vendors to define additional
sub-states. The type-safe equivalent is to define new subclasses of
the state classes.
public interface de.danet.an.workflow.api.ExecutionObject extends, de.danet.an.workflow.omgcore.WfExecutionObject {
// Public Methodspublic void changeState(de.danet.an.workflow.omgcore.WfExecutionObject.State newState)
throws RemoteException, InvalidStateException, TransitionNotAllowedException;public boolean debugEnabled()
throws RemoteException;public de.danet.an.workflow.omgcore.WfExecutionObject.State typedState()
throws RemoteException;
}
Inheritance Path. Section A.2.22, “Interface ExecutionObject”
public void changeState(de.danet.an.workflow.omgcore.WfExecutionObject.State newState)
throws RemoteException, InvalidStateException, TransitionNotAllowedException;Parameters
newState
state to change to.
Exceptions
InvalidStateException
if
newState
is an invalid
state for the execution object.
TransitionNotAllowedException
if the transition from the current
state to
newState
is not allowed.
RemoteException
if a system-level error occurs.
Type-safe equivalent to
WfExecutionObject.changeState()
.
public boolean debugEnabled()
throws RemoteException;Parameters
true
if the execution object is in
debugging mode
Exceptions
RemoteException
if a system-level error occurs
Checks if the execution object is in debugging mode.
public de.danet.an.workflow.omgcore.WfExecutionObject.State typedState()
throws RemoteException;Parameters
the state.
Exceptions
RemoteException
if a system-level error occurs.
Type-safe equivalent to
WfExecutionObject.state()
.
This interface represents an
ExternalReference
as
specified by XPDL.
public interface de.danet.an.workflow.api.ExternalReference extends, java.io.Serializable {
// Public Methodspublic java.net.URI location();public String namespace();public String xref();
}
1.1
Inheritance Path. Section A.2.23, “Interface ExternalReference”
public java.net.URI location();Parameters
location information
Returns the location information of the external document.
This exception is thrown by the
newInstance
method
of
WorkflowServiceFactory
.
public class de.danet.an.workflow.api.FactoryConfigurationError extends, java.lang.Error {
// Public Constructorspublic FactoryConfigurationError();public FactoryConfigurationError(String msg);public FactoryConfigurationError(String msg,
Throwable cause);
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Error-> Section A.2.24, “Error FactoryConfigurationError”
This class provides a description of a formal parameter as used for workflow processes and workflow applications.
public class de.danet.an.workflow.api.FormalParameterimplements, java.io.Serializable {
// Public Constructorspublic FormalParameter(String newId,
String newIndex,
FormalParameter.Mode newMode,
Object newType);
// Public Methodspublic boolean equals(Object obj);public int hashCode();public String id();public String index();public FormalParameter.Mode mode();public String toString();public Object type();
}
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
toString
,
wait
Inheritance Path. java.lang.Object-> Section A.2.25, “Class FormalParameter”
public FormalParameter(String newId,
String newIndex,
FormalParameter.Mode newMode,
Object newType);Parameters
newId
identifier of the formal parameter in String
newIndex
index of the formal parameter in String. In the 1.iteration if the new Index is not null, a warning will be generated.
newMode
mode of this formal parameter
newType
type of this formal parameter
Creates a new
FormalParameter
.
public boolean equals(Object obj);Parameters
obj
the object to compare with.
true
if the objects are equal.
Compare two formal parameter objects.
public String id();Parameters
a String representing the id value
Return the id of the formal parameter.
public String index();Parameters
a String representing the index value
Return the index of the formal parameter.
public FormalParameter.Mode mode();Parameters
the
FormalParameter.Mode
of the formal parameter.
Return the mode of the formal parameter.
public String toString();Parameters
the result.
Create string representation for debugging purposes.
public Object type();Parameters
the type of the formal parameter.
Return the type of the formal parameter. Types are represented
as defined for
ProcessMgr.contextSignature
.
Defines a class for representing priorities in a type save way.
public static final class de.danet.an.workflow.api.FormalParameter.Modeimplements, java.io.Serializable {
// Public Static Fieldspublic static final FormalParameter.Mode IN ;public static final FormalParameter.Mode INOUT ;public static final FormalParameter.Mode OUT ;
// Public Static Methodspublic static FormalParameter.Mode fromString(String text)
throws IllegalArgumentException;
// Public Methodspublic final String toString();
}
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
toString
,
wait
Inheritance Path. java.lang.Object-> Section A.2.26, “Class FormalParameter.Mode”
This interface extends the interface
WfResource
for resources
that are groups. The distinction of resource types is without relevance
to the workflow engine, but may be used to e.g. display resource types
differently in the user interface. Resource management services are not
required to make use of this interface, they may deliver all resources as
plain
WfResource
s. Application must therefore be
prepared to handle resources that only implement the base interface
WfResource
.
public interface de.danet.an.workflow.api.GroupResource extends, de.danet.an.workflow.omgcore.WfResource, java.io.Serializable {
}
Inheritance Path. Section A.2.27, “Interface GroupResource”
This exception is thrown by the
importProcessDefinitions
method of
ProcessDefinitionDirectory
and results from collected
errors.
public class de.danet.an.workflow.api.ImportException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic ImportException(String msg,
java.util.List prioritizedMessages);
// Public Methodspublic java.util.List messages();
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.2.28, “Exception ImportException”
public ImportException(String msg,
java.util.List prioritizedMessages);Parameters
msg
the main message of the exception.
prioritizedMessages
the given prioritized messages.
Construct a
ImportException
from a collecting error
handler. The warnings, errors, fatal error of the Exception are
taken from the error handler.
public java.util.List messages();Parameters
list with error messages (may be empty).
Return all messages, i.e. warnings, errors and fatal
errors. The value returned is a list of
PrioritizedMessage
.
This exception is raised if an invalid id is passed to a lookup method.
public class de.danet.an.workflow.api.InvalidIdException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic InvalidIdException(String msg);
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.2.29, “Exception InvalidIdException”
This exception is raised if an invalid key is passed to a lookup method.
public class de.danet.an.workflow.api.InvalidKeyException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic InvalidKeyException(String msg);
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.2.30, “Exception InvalidKeyException”
This class provides a
Batch
implementation that executes several invocations of remote objects
on the server in a single transaction and returns the results. This
class can be thought of as a "generic DTO".
public class de.danet.an.workflow.api.MethodInvocationBatchimplements, de.danet.an.workflow.api.Batch, java.io.Serializable {
// Public Constructorspublic MethodInvocationBatch();public MethodInvocationBatch(boolean stopOnException);
// Public Methodspublic void addInvocation(int result,
String method,
String[] argTypes,
Object[] args,
boolean discard);public void addInvocation(Object obj,
String method,
String[] argTypes,
Object[] args);public Object execute(Batch.Context ctx);public String toString();
}
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
toString
,
wait
Inheritance Path. java.lang.Object-> Section A.2.31, “Class MethodInvocationBatch”
public MethodInvocationBatch();Create a new empty method invocation batch. Equivalent to
MethodInvocationBatch(false)
.
public MethodInvocationBatch(boolean stopOnException);Parameters
stopOnException
if
true
execution is
interrupted on the first encountered exception
Create a new empty method invocation batch. The flag passed as parameter controls if an exception stops the batch execution.
public void addInvocation(int result,
String method,
String[] argTypes,
Object[] args,
boolean discard);Parameters
result
relative
index of the result to be used
for method invovation, i.e.
-1
is the previous result.
method
the method name.
argTypes
the argument types as strings suitable for
ClassLoader.loadClass
. May be
null
which is interpreted as "no parameters".
args
the actual arguments. May be
null
which is interpreted as "no parameters".
discard
if
true
the referenced result will
be removed from the result list.
Adds a method invocation on a previous result to the batch.
public void addInvocation(Object obj,
String method,
String[] argTypes,
Object[] args);Parameters
obj
the objects whose method is to be invoked.
method
the method name.
argTypes
the argument types as strings suitable for
ClassLoader.loadClass
. May be
null
which is interpreted as "no parameters".
args
the actual arguments. May be
null
which is interpreted as "no parameters".
Adds a method invocation to the batch.
public Object execute(Batch.Context ctx);Specified by: Method execute in interface Batch
Parameters
ctx
the execution context.
the execution result, which is of type
Result
.
Executes the registered method invocations one by one in a single transaction. Note that execution is terminated if an invoked method sets rollback only.
The result of an execution of this kind of batch.
public class de.danet.an.workflow.api.MethodInvocationBatch.Resultimplements, java.io.Serializable {
// Public Constructorspublic MethodInvocationBatch.Result(Object[] theResults,
boolean exceptionsOccured);
// Public Methodspublic Exception firstException()
throws IllegalStateException;public boolean hasExceptions();public Object result(int i);public java.util.Date resultAsDate(int i);public int resultAsInt(int i);public String resultAsString(int i);public Object[] results();public String toString();
}
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
toString
,
wait
Inheritance Path. java.lang.Object-> Section A.2.32, “Class MethodInvocationBatch.Result”
public MethodInvocationBatch.Result(Object[] theResults,
boolean exceptionsOccured);Parameters
theResults
the results attribute.
exceptionsOccured
the exceptions attribute.
Construct a new
Result
objects with the given
attributes.
public Exception firstException()
throws IllegalStateException;Parameters
the first exception.
Exceptions
IllegalStateException
if the result includes no exceptions.
Return the first exception in the result list.
public boolean hasExceptions();Parameters
true
if execeptions have occured.
Return
true
if any exceptions have occured
during batch execution.
public Object result(int i);Parameters
i
the index into the result array.
result.
Returns the result with the given index.
public java.util.Date resultAsDate(int i);Parameters
i
the index into the result array.
result as
Date
.
Returns the result with the given index as
Date
.
public int resultAsInt(int i);Parameters
i
the index into the result array.
result as
int
.
Returns the result with the given index as
int
.
This exception is thrown if a resource has become invalid.
public class de.danet.an.workflow.api.NoSuchResourceException extends, java.lang.Exception
implements, java.io.Serializable {
// Public Constructorspublic NoSuchResourceException(String msg);
}
Methods inherited from java.lang.Throwable
:
fillInStackTrace
,
getCause
,
getLocalizedMessage
,
getMessage
,
getStackTrace
,
initCause
,
printStackTrace
,
setStackTrace
,
toString
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
wait
Inheritance Path. java.lang.Object-> java.lang.Throwable-> java.lang.Exception-> Section A.2.33, “Exception NoSuchResourceException”
This interface identifies the data type "workflow participant" in a
ProcessDataInfo
object.
public interface de.danet.an.workflow.api.Participant {
// Public Methodspublic String getId();public String getName();public Participant.ParticipantType getParticipantType();public Object getResourceSelection();
}
Inheritance Path. Section A.2.34, “Interface Participant”
public String getId();Parameters
a String representing the id value
Get the id of the participant.
public String getName();Parameters
a String representing the name value
Get the name of the participant.
This class defines the participant type for a participant.
public static final class de.danet.an.workflow.api.Participant.ParticipantTypeimplements, java.io.Serializable {
// Public Static Fieldspublic static final Participant.ParticipantType HUMAN ;public static final Participant.ParticipantType ORGANIZATIONAL_UNIT ;public static final Participant.ParticipantType RESOURCE ;public static final Participant.ParticipantType RESOURCE_SET ;public static final Participant.ParticipantType ROLE ;public static final Participant.ParticipantType SYSTEM ;
// Public Static Methodspublic static Participant.ParticipantType fromString(String text)
throws IllegalArgumentException;
// Public Methodspublic final boolean isHuman();public final boolean isOrganizationUnit();public final boolean isResource();public final boolean isResourceSet();public final boolean isRole();public final boolean isSystem();public final String toString();
}
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
toString
,
wait
Inheritance Path. java.lang.Object-> Section A.2.35, “Class Participant.ParticipantType”
public static final Participant.ParticipantType ORGANIZATIONAL_UNIT ;ORGANIZATIONAL_UNIT ParticipantType.
public static Participant.ParticipantType fromString(String text)
throws IllegalArgumentException;Parameters
text
participant type name to search
participant type object
Exceptions
IllegalArgumentException
if
text
is not a valid
participant type name.
Get a participant type by name.
public final boolean isHuman();Parameters
true
if the type is "HUMAN".
Checks if the type is "HUMAN".
public final boolean isOrganizationUnit();Parameters
true
if the type is "ORGANIZATIONAL_UNIT".
Checks if the type is "ORGANIZATIONAL_UNIT".
public final boolean isResource();Parameters
true
if the type is "RESOURCE".
Checks if the type is "RESOURCE".
public final boolean isResourceSet();Parameters
true
if the type is "RESOURCE_SET".
Checks if the type is "RESOURCE_SET".
public final boolean isRole();Parameters
true
if the type is "ROLE".
Checks if the type is "ROLE".
This class presents a prioritized message that will be internationalized using the specified resource bundle and the referenced entry. For details see the description of its class contructor.
public class de.danet.an.workflow.api.PrioritizedMessageimplements, java.io.Serializable {
// Public Constructorspublic PrioritizedMessage(PrioritizedMessage.Priority priority,
String message);public PrioritizedMessage(PrioritizedMessage.Priority priority,
String message,
Object[] data);
// Public Methodspublic String message();public String message(java.util.Locale locale);public PrioritizedMessage.Priority priority();public String toString();public String unmappedMessage();
}
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
toString
,
wait
Inheritance Path. java.lang.Object-> Section A.2.36, “Class PrioritizedMessage”
public PrioritizedMessage(PrioritizedMessage.Priority priority,
String message);Parameters
priority
the priority of the given message.
message
a message or a resource and key reference.
message()
Constructs a prioritized message. If the message has the format
"
a.resource.bundle.base.name#key
" it is interpreted as the
base name of a <code>ReosurceBundle</code> and the key of an entry in this
resource bundle.
public PrioritizedMessage(PrioritizedMessage.Priority priority,
String message,
Object[] data);Parameters
priority
the priority of the given message.
message
a message or a resource and key reference.
data
additional data used when formatting the message.
message()
Constructs a prioritized message. If the message has the format
"
a.resource.bundle.base.name#key
" it is interpreted as the
base name of a <code>ReosurceBundle</code> and the key of an entry in this
resource bundle.
If the parameter
data
is not
null
,
the message (or the string looked up in the resource bundle)
will be fomatted using <code>MessageFormat.format</code>.
public String message();Parameters
the message.
message(java.util.Locale)
Returns the message. If the message has the format
"
a.resource.bundle.base.name#key
", it will be
internationalized using the specified resource bundle and the
referenced entry with the default <code>Locale</code>.
public String message(java.util.Locale locale);Parameters
locale
the
Locale
to be used for
resource bundle lookup.
the message.
Returns the message. If the message has the format
"
a.resource.bundle.base.name#key
", it will be
internationalized using the specified resource bundle and the
referenced entry using the given <code>Locale</code>.
public PrioritizedMessage.Priority priority();Parameters
the priority of the message.
Returns the priority of the message.
This class represents the priority of a given message. It was taken over from org.apache.log4j.Priority to avoid the dependence of the log4j library.
public static class de.danet.an.workflow.api.PrioritizedMessage.Priorityimplements, java.io.Serializable, java.lang.Comparable {
// Public Static Fieldspublic static final PrioritizedMessage.Priority DEBUG ;public static final PrioritizedMessage.Priority ERROR ;public static final PrioritizedMessage.Priority FATAL ;public static final PrioritizedMessage.Priority INFO ;public static final PrioritizedMessage.Priority WARN ;
// Protected Constructorsprotected PrioritizedMessage.Priority(int level,
String levelStr);
// Public Methodspublic int compareTo(Object other);public String toString();
}
Methods inherited from java.lang.Object
:
clone
,
equals
,
finalize
,
getClass
,
hashCode
,
notify
,
notifyAll
,
toString
,
wait
Inheritance Path. java.lang.Object-> Section A.2.37, “Class PrioritizedMessage.Priority”
protected PrioritizedMessage.Priority(int level,
String levelStr);Parameters
level
the level of the priority.
levelStr
the string representation of the priority.
Constructor of the priority of a message.
public static final PrioritizedMessage.Priority DEBUG ;The
DEBUG
priority designates fine-grained
informational events that are most useful to debug an
application.
public static final PrioritizedMessage.Priority ERROR ;The
ERROR
level designates error events that
might still allow the application to continue running.
public static final PrioritizedMessage.Priority FATAL ;The
FATAL
level designates very severe error
events that will presumably lead the application to abort.
public static final PrioritizedMessage.Priority INFO ;The
INFO
level designates informational messages
that highlight the progress of the application at coarse-grained
level.
public static final PrioritizedMessage.Priority WARN ;The
WARN
level designates potentially harmful
situations.