Extensibility Mechanisms in OBE
OBE is modular in design and many aspects of its behaviour and
capabilities can be readily customized or extended. There are several
mechanisms for achieving this.
Workflow Services
Workflow Services provide the
basic infrastructure required to support the workflow engine, such as
persistence and object lookup, activity enactment, event management,
computation and conversion, resource storage, parser support and tool
invocation. There are several possibilities for extensibility:
Custom Service Implementation
All workflow services are defined as interfaces. You can create your
own service implementation and specify the class name in
ServiceManager.properties
. For example, you might use this approach
in order to:
- Manage all configuration data using JMX.
- Store your process definitions or document resources in a WEBDAV
repository.
- Persist all your workflow instance data using Hibernate or Spring.
- Integrate the OBE security realm tightly with your enterprise LDAP
directory.
To ensure that your classes are accessible to the Service Manager, add the
name(s) of the custom jar(s) containing them to the
engine.runtime.jars
ant
build property when you prepare your
development environment. This will ensure that obeengine.jar contains a
MANIFEST.MF Class-Path
entry that references your jars. Ensure that
you deploy all jars together in the same EAR or directory (obeserver.ear
and
lib
, typically & respectively).
Repository Metadata
Many of the workflow services manage a registry of metadata
entries,
of which there are many subclasses. Each registry entry represents a
type of resource or service of the kind managed by the associated workflow
service, or a particular service configuration, or
a particular resource instance. Each of the basic service
implementations supplied with OBE stores its metadata in a file
named Basic<service-name>.xml
, which
resides either in the ${obe.config.dir}
directory or in
the META-INF/services
folder of obeconfig.jar
.
Custom Repository Metadata
Entries
A repository entry can extend another entry, thereby inheriting all
those parent entry's non-primitive properties which the child entry does not
override (by specifying a value).
In this way it is possible to set up arbitrary property value inheritance
hierarchies.
You can extend the runtime capabilities of the workflow engine by
adding your own custom entries.
<types>
...
<meta-data id="type-id" xsi:type="obe:obe-tag">
<!-- Inheritable properties as appropriate for the type. -->
...
</meta-data>
</types>
<entries>
...
<entry>
<obe-tag id="entry-id1" type="type-id" ...>
<!-- Overridden properties follow. -->
...
</obe-tag>
</entry>
<entry>
<obe-tag id="entry-id2" type="entry-id1" ...>
<!-- Overridden properties follow. -->
...
</obe-tag>
</entry>
</entries>
- In the above example entry
-id1
is a sub-type of type-id
, and entry-id2
is a
sub-type of entry
-id1
. Workflows may reference both entry-id1
and entry
-id2
but not type-id
.
Custom Repository Metadata
Types
For some services you can create your own custom metadata types to
describe corresponding classes which implement custom runtime
behaviour. Typically you would extend one of the metadata classes
managed by the service. Metadata objects are JavaBeans and must follow
the JavaBeans
design patterns. Register your custom metadata type in the XML
configuration file for the service by declaring it in the
<types>
section and (usually) one or more entries in the
<entries>
section as shown below.
N.B. At the time of writing (29th Oct. '05 - Castor 0.9.9)
bug CASTOR-1039 prevents the use of
custom-tag
as an element name for an XML field which uses Castor's
'location' feature. Thus in the types section we have to use
xsi:type
to specify the type.
The example below shows a custom metdata class fqcn
being mapped to the XML element
prefix:custom-tag
, where the prefix
prefix
denotes the XML namespace URI
uri
.
<repository ... xmlns:prefix="uri">
<types>
...
<meta-data id="typeid" xsi:type="prefix:custom-tag">
<display-name>display-name</display-name>
<description>descriptive-text</description>
<author>company-name|person-name</author>
<!-- Other inheritable properties as appropriate for the type. -->
...
</meta-data>
</types>
<entries>
...
<entry>
<!-- type attribute declares instance inheritance from typeid. -->
<prefix:custom-tag id="entry-id" type="typeid" ...>
<!-- Overridden properties follow. -->
...
</prefix:custom-tag>
</entry>
</entries>
</repository>
- typeid
- The unique ID for this type
- prefix
- Custom XML namespace prefix.
- uri
- Custom XML namespace URI.
- custom-tag
- A custom tag name (see below) to identify instances of your custom
metadata type.
- entry-id
- Unique entry identifier. This is how you reference the new feature from
its own subtypes and from workflows.
You also need to tell Castor how to serialize and deserialize instances
of your metadata class to and from the XML file. You do this by adding
an entry in castor-map.xml
after the metadata class which yours
extends, thus:
<!-- You can extend any subclass of AbstractMetaData. -->
<class name="fqcn" extends="org.obe.client.api.repository.AbstractMetaData">
<map-to xml="custom-tag" ns-prefix="prefix" ns-uri="uri" />
<description>Mapping for class fqcn</description>
<field name="fieldName" type="fqtn" required="boolean">
<bind-xml name="field-name" node="element|attribute|text" />
</field>
...
</class>
- fqcn
- Fully qualified name of the metadata class.
- custom-tag
- A custom tag name to identify instances of the class (more convenient
than always using
xsi:type
).
- fieldName, fqtn, field-name, etc.
- For complete details, consult the Castor
documentation. For examples, consult the default configuration
files.
Tool Agents
Tool Agents enable the workflow engine to make outbound invocations to
external logic, using practically any available technology for which a
Java API exists. There are two ways to add new tool agents:
Custom Tool Entry
This is the 'Custom Repository Metadata Entry' case discussed above, applied to
the ToolAgentFactory. Simply add an entry of a predefined tool agent type
to BasicToolAgentFactory.xml
,
overriding properties as appropriate (class-name, method,
method-sig
, etc.). The following example shows how you
could register two Java methods from the class
com.company.workflow.SalesOrderProcs
under the tool
IDs fufill
and cancel
:
<types>
...
<meta-data id="JavaMethod" xsi:type="obe:java-method">
...
</meta-data>
<meta-data id="soproc" xsi:type="obe:java-method">
...
<class-name>com.company.workflow.SalesOrderProcs</class-name>
</meta-data>
</types>
<entries>
...
<entry>
<java-method id="fulfill" type="soproc" ...>
...
<method>fulfillOrder</method>
<method-sig>
<parm-type>String</parm-type>
</method-sig>
</java-method>
</entry>
<entry>
<java-method id="cancel" type="soproc" ...>
...
<formal-parameters>
<formal-parameter id="orderNumber" mode="IN">
<data-type>
<basic-type type="STRING"/>
</data-type>
</formal-parameter>
</formal-parameters>
<method>cancelOrder</method>
<method-sig>
<parm-type>String</parm-type>
</method-sig>
</java-method>
</entry>
Note that XPDL requires a tool's invocation interface to be defined with
<xpdl:FormalParameter>
elements declared in the XPDL.
Alternatively, the tool can be defined by an <
xpdl:
ExternalReference>
element, in which case OBE interprets the
location
attribute as the tool identified in the ToolAgentFactory.
You can place <formal-parameter>
elements inside the tool
agent metadata; the workflow engine uses them for tools which are defined in
XPDL using an <
xpdl:
ExternalReference>
(and therefore lack <xpdl:FormalParameters>
).
Variable Actual Parameter
Lists
When declared in the tool agent repository entry, formal parameters are
not subject to the usual XPDL constraint that the formal parameter
count and the actual parameter count must match. If an activity
supplies more actual parameters than formal parameters are
declared, the extra actual parameters are all assigned the mode and
data type of the last formal parameter. This allows for a C / JDK 5
style 'varargs' definition of a tool's invocation signature. It allows,
for example, tool agents such as UpdateProcessAttributes
to display
and update any number of process attributes in one form.
Custom Tool Agent Type
This is the 'Custom Repository Metadata Type' case discussed above,
applied to the ToolAgentFactory. You can develop a custom tool agent
type to encapsulate a technology for which OBE does not provide an
out-of-the-box adapter, such as the J2EE
Connector Architecture. The steps are as follows:
- Decide what metadata are required and develop a custom tool
agent metadata class to hold them.
- Develop a custom tool agent
implementation to actually perform the
invocation to the target service, using the metadata settings and the
actual parameters supplied by activities in workflow definitions.
- Inform Castor how to marshall and unmarshall the class to and from
XML:
- Add a
<class>
description to
castor-map.xml
to match the metadata class.
- Include
<field ...>
elements for all fields
that the class adds.
- Include a
<map-to xml="custom-tag"
ns-prefix="prefix" ns-uri="uri">
element to specify the XML mapping to a custom tag name in an XML
namespace of your choice (don't use the obe: namespace prefix).
- As shown above, add a
<metadata id="typeid"
xsi:type="prefix:custom-tag">
entry to the <types>
section of
BasicToolAgentFactory.xml
, identifying your new tool agent type.
- As shown above, one or more
<custom-tag
.../>
entries to the <entries>
section
of BasicToolAgentFactory.xml
, to provide one or more useful
tool agent configurations.
- Develop workflows that use the new tool agent(s).