12.1: Example service invocation plugin
To get started, you can download from the JOpera website
http://www.jopera.ethz.ch/download/demos
a sample Hello World demo adapter.
12.2: Setting up a new service invocation plugin
This section describes how to create a new Eclipse plugin which extends the extension-points needed to insert a service invocation plugin into JOpera.
A new Eclipse plugin project should be created with a dependency to the ch.ethz.jopera.kernel and ch.ethz.jopera.core plugins.

Figure 12.1: Dependencies of a Subsystem plugin
Once the dependency are set, the extensions can be declared by clicking on the corresponding tab.
12.3: The ISubSystem Interface
This interface must be implemented by all service invocation plugins. It contains only two methods.
12.4: The IJob Interface
The information describing the service invocation to be performed by the plugin is packaged into an IJob object, which
is passed as a parameter to the execute method. This object is used to store all input/output parameters of the
service invocation, and also to inform JOpera of the final outcome of the invocation, i.e., whether it was successful or it failed.
The most important methods of IJob are:
- getInput()
- getActiveCommand()
- getOutput()
- getSystemOutput()
- setState()
- notifyFinished()
Their usage will be explained in the following sections. First we discuss how to transfer control, then how to report failures in the invocation and finally how to transfer data.
12.5: Control flow mapping
The execute method of the ISubSystem interface is called by JOpera in a dedicated thread to perform the transfer of control from a running task to the corresponding service provider.
This can happen synchronously (a thread waits) or asynchronously (initiated by a thread and completed by another).
12.5.1: Synchronous Service Invocation
In the simplest case, this happens synchronously. This means that the service invocation is completed by the time the execute method returns.
This is straightforward to implement as all the code for initiating the invocation (e.g., sending a request to the service provider)
and completing it (e.g., reading and decoding the response) is contained in the execute method, which can be structured in the following three steps
- Call the service provider
- Wait for an answer
- Retrieve the response
12.5.2: Asynchronous Service Invocation
Depending on whether the service is invoked locally or remotely and depending on how long the service invocation typically lasts, it
may not be efficient to keep waiting for an answer as this keeps the thread running the execute method busy.
To address this problem, as an alternative, it is also possible to use the execute method to only perform step 1., i.e., initiate the call, and
handle the other steps asynchronously so that the thread invoking the service does not block and can be used by JOpera to run other tasks.
In this case, it is the responsibility of the service invocation plugin to notify JOpera whenever it detects that the
service has completed its execution. Since the execute method has already returned, the plugin must use its own thread to run the following code:
job.setState(State.FINISHED);
job.notifyFinished();
This code will inform JOpera of the asynchronous completion of the
job representing the service invocation.
12.6: Failure detection
It is the responsability of the plugin to provide the necessary logic to detect whether a service invocation was successful.
To do so, a successful invocation should use the following code:
job.setState(State.FINISHED);
If a failure occurred, e.g., a timeout, or any kind of exceptional condition has been detected, JOpera can be notified with the following:
job.setState(State.FAILED);
Additional information about the failure, e.g., describing its cause with some error messages, can be stored in the plugin-specific system output parameters.
12.7: Data flow mapping
In addition to transferring control, the service invocation adapter is responsible for transferring data between JOpera and the service provider for the specific kind of service. The subsystem is responsible for implementing the required encoding/decoding of the data.
JOpera structures the data parameters exchanged with the subsystem as follows. First of all, a distinction is made between input and output data parameters. From the point of view of the service, input data is sent as part of the request, whereas output data is retrieved as part of the response.
JOpera also distinguishes between application-level data from system-level metadata.
The IJob interface provides access to all of these parameters, identified by their name, through the following Maps
- 'public Map getInput();' //get input data parameters
- 'public Map getActiveCommand();' //get input metadata parameters (read-only)
- 'public Map getOutput();' //set output data parameters
- 'public Map getSystemOutput();' //set output metadata parameters
Note:
The values for the parameters stored in these maps can be set to any Java Serializable data type.
12.8: Threading model
JOpera instantiates a new object of the given service invocation plugin class for each service invocation to be performed.
Furthermore, JOpera calls the execute method of the newly created object from within a dedicated thread.
Therefore, since JOpera already handles the multithreaded issues for the concurrent invocation of multiple services,
the plugin -- under normal circumnstances -- should not have to fork off additional threads to perform the invocation.
12.9: Example Code for Synchronous invocation
void Execute(IJob job)
{
//take the system input parameters
Map c = job.getActiveCommand();
//do something with it!
//set system output parameters
job.getSystemOutput().put("sys_output",...);
//set output parameters
job.getOutput().put("output",...);
//detect failures (somehow) and set the outcome of the job
if (ok)
job.setState(State.FINISHED);
else
job.setState(State.FAILED);
}
12.10: Example Code for Asynchronous invocation
void Execute(IJob job)
{
//take the system input parameters
Map c = job.getActiveCommand();
//start running something with it!
//do not change the state of the job
}
//it is the responsability of the plugin to call this method
//from its own thread whenever the service invocation has completed
//asynchronously
void Complete(IJob job)
{
//set system output parameters
job.getSystemOutput().put("sys_output",...);
job.getOutput().put("output",...);
if (ok)
job.setState(State.FINISHED);
else
job.setState(State.FAILED);
//notify JOpera about it
job.notifyFinished();
}
12.11: Example Code for the Signal Method
This is the simplest implementation of the signal method. No matter what signal is given to the subsystem, the state of its job is left unmodified, i.e., it remains Running.
public State Signal(int Signal)
{
//by default indicate that the signal
//did not affect the running job
return State.RUNNING;
}