Activities provide one of the extension points of OGSA-DAI through which users can add new functionality. We described the role of activities in our page on interacting with data service resources
This tutorial describes how to extend OGSA-DAI by writing and deploying a new activity. We use a stringTokenizer activity as a basis for the example. Note that OGSA-DAI already includes such an activity described on the stringTokenizer activity page.
The stringTokenizer activity will sit between two activities at an intermediate stage in an activity chain. It will separate a sequence of string input data into smaller tokens for output. The set of delimiters used to separate tokens may be specified. For example, using comma, colon and space as delimiters, the following string input data:
nichiyoobi,getsuyoobi:kayoobi suiyoobi,mokuyoobi:kinyoobi doyoobi
will be broken into the following seven tokens:
nichiyoobi
getsuyoobi
kayoobi
suiyoobi
mokuyoobi
kinyoobi
doyoobi
There are four stages involved in writing a basic activity:
Every activity has an XML-Schema that describes the structure of the activity XML element that will be written by clients in perform documents. This element is known as an activity element and its XML-Schema will define the inputs and outputs of the activity as well as any additional configuration details. Occurrences of activity elements are used within perform documents to indicate which activities should be performed by a data service resource.
For this example, the XML Schema for the stringTokenizer activity will be constructed by modifying an XML Schema template. Start by copying this Activity Schema Template into a new file named string_tokenizer.xsd. Next make the following changes:
<xsd:element name="delimiters" minOccurs="0" maxOccurs="1"> <xsd:complexType> <xsd:attribute name="value" use="required"> <xsd:simpleType> <xsd:restriction base="xsd:string"/> </xsd:simpleType> </xsd:attribute> </xsd:complexType> </xsd:element>
This configuration will allow a user to specify the set of characters that they wish to use as delimiters. For example:
<delimiters value=", :"/>
will use comma, space and colon characters as separators.
An example of the completed string_tokenizer.xsd XML Schema is available here.
Every activity has an implementation class that performs the action associated with the activity. Before writing an activity implementation class it is useful to understand the life-cycle of the activity. This is shown using a UML sequence diagram in Figure 1.
When a perform document is received by a data service resource, the activity elements are first extracted. An activity object corresponding to each activity element is then created. The activity element is passed to the activity object constructor. After construction, the context and session for the activity is set using the configureContext method. From this point onwards, the activity object is able to interact with the context and session in order to access the data resource, inputs and outputs, user credentials and session attributes.
Following construction and configuration, the initialise method is invoked to perform any initialisation that the activity requires prior to activity processing.
Afterwards, the activity processing stage commences. This involves repeated invocations of the process method until the activity status indicates that processing is complete. On the first invocation, the processFirst method will be called then the processBlock method. On subsequent invocations only the processBlock method will be called.
When there is no more processing to do, the activity must indicate so by calling the setCompleted method. Afterwards, the process method shall cease to be invoked. After an activity has completed it will be made eligible for garbage collection and will duly be cleaned up by the JVM.
Writing an activity implementation class involves some or all of the following steps:
Returning now to the example, the stringTokenizer activity will need an implementation class. The processing task is to split a stream of input data into a sequence of tokens for output. Start by copying the Activity Java Template into a new file named StringTokenizerActivity.java. Then make the following changes:
String inputName = ((Element) element.getElementsByTagNameNS( OGSADAIConstants.TYPES_NAMESPACE, "stringBlocksInput").item(0)).getAttribute("from"); String outputName = ((Element) element.getElementsByTagNameNS( OGSADAIConstants.TYPES_NAMESPACE, "stringTokensOutput").item(0)).getAttribute("name") ;
NodeList list = element.getElementsByTagNameNS( OGSADAIConstants.TYPES_NAMESPACE, "delimiters"); mDelimiters = (list.getLength()>0) ? ((Element) list.item(0)).getAttribute("value") : " ";
An example of the completed StringTokenizerActivity.java class is available here.
If an activity needs to interact with a data resource then this is typically done through the data resource accessor object. The data resource accessor object will implement the uk.org.ogsadai.dataresource.DataResourceAccessor interface. Activities can get a reference to the data resource accessor object object via the mContext member variable of the base Activity class:
DataResourceAccessor dataResourceAccessor = mContext.getDataResourceAccessor();
The mContext field also provides access to the activity inputs and outputs and security context. Note that the mContext field must not be used from within an activity constructor, because it has not yet been initialised. See the description of the activity life-cycle above for more details. It can however be used from within the initialise, processFirst and processBlock methods.
This DataResourceAccessor interface is not much use to activity developers so you will wish to cast the object returned by the getDataResourceAccessor() method to another interface or class. This would normally be carried out within the initialise method in order to initialise a field. The core data service resources provided with OGSA-DAI can be cast to the following interfaces:
Relational Data Resource Accessor | |
Accessor class: | uk.org.ogsadai.dataresource.JDBCDataResourceAccessor |
Interface: | uk.org.ogsadai.dataresource.JDBCConnectionProvider |
XML Data Resource Accessor | |
Accessor class: | uk.org.ogsadai.dataresource.XMLDBDataResourceAccessor |
Interface: | uk.org.ogsadai.dataresource.XMLDBCollectionProvider |
File System Data Resource Accessor | |
Accessor class: | uk.org.ogsadai.dataresource.FilesDataResourceAccessor |
Interface: | uk.org.ogsadai.dataresource.FileAccessProvider |
It is strongly advised that you cast to the interface rather than the accessor class. This will allow your activity to work with any data service accessors that implement the interface. For example, if you are developing an activity that connects to a relational database using JDBC then the DataResourceAccessor object should be cast to the JDBCConnectionProvider interface as show here:
JDBCConnectionProvider connectionProvider = (JDBCConnectionProvider) mContext.getDataResourceAccessor();
The connectionProvider object can then be used to obtain and release JDBC connection to the data resource.
If an activity needs to interact with a session, the uk.org.ogsadai.sessions.Session interface can be accessed using the getSession method of the base Activity class. The session allows the activity to store or access session attributes, session streams and data service resource properties.
Session session = getSession(); SessionAttribute attribute = session.getAttribute(new QName("MyAttribute")); Properties properties = session.getProperties();
If an activity needs to interact with the authorizer which controls access to resources and activities, the AccessAuthorizer interface can be accessed using the getAuthorizer method of the ActivityContext.
AccessAuthorizer authorizer = mContext.getAuthorizer();
For more information on access authorization see the How to Authorize Access to Resources and Activities tutorial.
If you do not wish to interact with your new activity using the Client Toolkit then this step can be ommitted. Otherwise a Client Toolkit activity implementation class is needed. This is a client-side class that corresponds to the server-side activity. The main responsibilities of such a class are to generate the activity element for embedding in a perform document, and to provide access to the results of the activity in a convenient form.
For this example, the Client Toolkit activity implementation will be written by modifying a Client Toolkit Activity Java Template. Note that the class in the template extends uk.org.ogsadai.client.toolkit.activity.Activity. This is an abstract base class for all client activity implementations. It provides common functionality and defines the abstract generateXML method that must be implemented by concrete sub-classes. An implementation of this method must generate the XML activity element suitable for embedding into a perform document.
Start by copying the template into a new file named StringTokenizerActivity.java. Make sure that the implementation file from step 2 is not overwritten by saving this file in a different directory. To complete the client activity implementation, follow the steps below:
/** * Constructs an activity to tokenize the input using the specified * delimiters. * * @param delimiters the delimiters used to separate tokens */ public StringTokenizerActivity(final String delimiters) { addInput("String blocks input"); addOutput("String tokens output"); mDelimiters = delimiters; }
protected String generateXML() { final StringBuffer sb = new StringBuffer(); sb.append("<stringTokenizer name=\""); sb.append(getName()); sb.append("\">\n"); // stringBlocksInput sub-element sb.append(" <stringBlocksInput from=\""); sb.append(getInputParameters()[0].getOutputName()); sb.append("\"/>\n"); // delimiters sub-element sb.append(" <delimiters value=\""); sb.append(mDelimiters); sb.append("\"/>\n"); // stringTokensOutput sub-element sb.append(" <stringTokensOutput name=\""); sb.append(getOutputs()[0].getName()); sb.append("\"/>"); sb.append("</stringTokenizer>"); return sb.toString(); }
An example of a completed Client Toolkit String Tokenizer Activity is provided.
Once you have defined an XML schema, provided a Java implementation, and optionally written a Client Toolkit activity, your activity is ready to be installed into OGSA-DAI. To install a new activity:
$ javac my/package/StringTokenizerActivity.javaEnsure that the CLASSPATH environment variable contains ogsadai-core.jar and
<activity name="ACTIVITY-NAME" implementation="ACTIVITY-IMPLEMENTATION-CLASS" schema="ACTIVITY-XML-SCHEMA"/>For example:
<activity name="stringTokenizer" implementation="my.package.StringTokenizerActivity" schema="string_tokenizer.xsd"/>
It should be noted that the name attribute here is case sensitive, and specifies the activity element name that will be used within perform documents.
Now the new activity will be available when the service container is restarted. The activity element can be embedded into perform documents sent to any OGSA-DAI services that are configured using the activity configuration documents you modified above.
To test your activity try sending the following perform document using the End-to-end Client. The dataStore activity sets up the data which is then passed to your new activity. You should see from the output that the delimiter characters have been removed.
<perform xmlns="https://ogsadai.org.uk/namespaces/2005/10/types"> <dataStore name="parameters"> <item>nichiyoobi,getsuyoobi:kayoobi suiyoobi</item> <item>mokuyoobi:kinyoobi doyoobi</item> <itemCursor name="dataStoreOutput"/> </dataStore> <stringTokenizer name="myTokenizer"> <stringBlocksInput from="dataStoreOutput"/> <delimiters value=" ,:" /> <stringTokensOutput name="tokenOutput"/> </stringTokenizer> </perform>
If you wrote a Client Toolkit activity class for the new activity, then clients written using the Client Toolkit APIs can also make use of the new activity.
This example has shown how to write a simple activity and provided some general guidelines. For more information it is recommended that you download the OGSA-DAI source distribution and examine the source code. The activities provided with OGSA-DAI are stored in sub-packages of uk.org.ogsadai.activity and the client activities within sub-packages of uk.org.ogsadai.client.toolkit.activity. The activities that are included with OGSA-DAI are described on the Activities Page of the documentation.
Up: OGSA-DAI User Guide | ||
© International Business Machines Corporation, 2002-2006 | © The University of Edinburgh, 2002-2006 |