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:
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: