Skip to end of metadata
Go to start of metadata

This is part of the tutorial Tutorial - Service invocation plugin

Configuring the service instance

After seeing our generated service appear when running the Taverna Workbench in developer mode, we will go into what the code of this activity actually do, and make a few modifications.

Expand the package uk.ac.manchester.cs.img.myfancytool.taverna (or equivalent) in the myfancytool-activity project. Open ExampleActivity.java.

Configuration

When an activity like ExampleActivity is added to a workflow, it will be created using the default/empty constructor. It will then be configured with a configuration bean. Different activities are configured with different types of configuration beans, in this case the ExampleActivity is implementing AsynchronousActivity<ExampleActivityConfigurationBean>, meaning that its configure() method expects a ExampleActivityConfigurationBean parameter.

A configuration bean will typically contain the specific details for realising an activity instance. For instance the WSDL activity needs to be configured with the location of the WSDL specification and the method name, the nested workflow activity needs to be configured with a workflow definition, and the simple String constant activity needs to be configured with the string to return.

When a workflow definition is stored to disk, Taverna will serialize which plugin the activity is from (by storing the Maven groupId, artifactId and version), the activity classname uk.ac.manchester.cs.img.myfancytool.taverna.ExampleActivityConfigurationBean and the properties from its configuration beans. The configuration bean is serialised using XML Beans, but this might change in later versions of Taverna.

Open the ExampleActivityConfigurationBean. You will notice that this example configuration is a standard JavaBeanwith two properties exampleString and exampleUri. Although not a requirement by Taverna's current workflow serialisation, it is a good idea to make the bean implement the java.io.Serializable interface. Other than that you are free to create properties as you see fit, but the properties must be either 'simple' Java types like String, int and boolean, or another JavaBean.

In this example bean we'll pretend that exampleUri specifies the service location, and exampleString specifies which method to invoke on the service. When you customize this configuration bean you should remove these fields, getters and setters and replace them with your own.

Let's return to the ExampleActivity. Have a look at the configure(ExampleActivityConfigurationBean) method.

Remember the configure method is called when an activity is added to a workflow. It is also called when a workflow definition is loaded, and if a user dialogue modifies the configuration. We'll come back to how the activity configuration beans are created in the user interface when we look at myfancytool-activity-ui later.

The configure method is responsible for two things:

  • Storing the configuration bean for later use during invocation and serialisation
  • Create input and output ports, potentially depending on configuration

The ActivityConfigurationException can be thrown if something goes wrong during configuration, in this example a simple sanity check of the bean is performed, but this could also be thrown for instance if the server is not found or something else goes wrong.

In this example the fictional MyClient is created at configuration time. You can choose to configure your client libraries at configuration time or invocation time, but remember that there could be a period between when an activity is configured (ie. when activity is added or workflow is opened) and when an activity is invoked (when that part of the workflow is run). Also note that if there are iterations, the activity would be invoked several times. Also note that while editing a workflow, no invocations will be performed on the activity, as on execution a second copy of the activity will be created and configured by Taverna.

The getConfiguration() method simply return the bean last passed to configure().

The last part of configure is to create input and output ports.

Creating input and output ports

The configure() is also responsible for creating the activity input and output ports. Service ports are similar to method parameters in Java, different values can be provided from different parts of the workflow. The service can also return more than one output. It is not required for all ports to be connected at execution time (although the invocation can fail if a required input port is missing), but the ports need to be specified by the activity at configuration time.

For clarity, this example has separated this out to a configurePorts() method.

First the removeInputs() and removeOutputs() calls, inherited from the superclass net.sf.taverna.t2.workflowmodel.processor.activity.AbstractAsynchronousActivity will remove any existing port definition. This point is important to be able to support reconfiguring of an existing activity instance, typically because the user interface has a dialogue to change bits of the configuration.

In this example the service will always have the input port firstInput and the output ports simpleOutput and moreOutputs. The port names are arbitrary, in the example we have made them string constants to make sure we don't misspell them when we use them later in the executeAsynch() method.

As also shown in this example, the activity is free to add and remove ports depending on the configuration. In this case an additional input port extraData is added together with the additional output report only if the configuration bean's exampleString is equal to "specialCase". This feature can also be used for cases where the service implementation does some kind of lookup to see what kind of inputs and outputs the actual service expects and exposes - in the case of the WSDL activity this is achieved by parsing the web service definition (the WSDL) and looking up the operation name, then dynamically creating inputs and outputs matching the web service parameters.

Self-describing configurations
Some services have the full port definitions as part of their configuration bean. One example of this is the Beanshell activity, where the user interface allow the workflow designer to specify inputs and outputs that are accessed within the beanshell script. Such definitions can be supported by having the configuration bean of the activity subclass net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityPortsDefinitionBean, from within configure() you can then simply call configurePorts(configurationBean) which would create the ports according to the configuration bean. (You are of course free to also create additional ports in this case, but would then have to check manually for port name conflicts. Remember to do add these after the call to configurePorts(), as it also does the port removal.)

Port types and depth

You might notice some numbers and classnames in the calls to addInput() above. For instance:

The second parameter 0 indicates that this port is of depth 0, meaning individual values. The last parameter String.class is the value type that this port expects the incoming data reference to be rendered as. (more on this below).

If we instead say a depth larger than 0, the service will receive a list of values (depth 1), list of lists of values (depth 2) and so on. For example:

Here we are saying that we expect a list of values (depth 1), and each value should be possible to retrieve as a byte array byte[], typically containing binary data. One could argue that this would actually be depth 2 as you have a list of arrays, but as it is seldom useful to deal with lists of bytes, Taverna treats byte arrays as individual values, the same way as Strings, both being depth 0. If you wanted just a single byte array, you could do addInput(IN_EXTRA_DATA, 0, true, null, byte[].class);

For the output ports the requirements are only on the depth, so if a single value is to be returned, it will be of depth 0:

And for a list of values, depth 1:

Next, let's have a look at what happens when invoking the service.


This is part of the tutorial Tutorial - Service invocation plugin

Labels

tutorialservice tutorialservice Delete
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.