The Handler Framework

From GCube System
Revision as of 02:10, 12 September 2009 by Fabio.simeoni (Talk | contribs) (GCUBEHandler)

Jump to: navigation, search

One way to characterise the overall behaviour of a service is in terms of the tasks that the service is designed to carry out. Interacting with a target service in the process of satisfying a client request is a common example of a task; monitoring some of the local resources at regular intervals is another. In many cases, modelling such tasks with dedicated components improves their maintainability and reusability. In particular, the same task components can be customised and reused in different parts of the service implementation or assembled in some guise to form more complex tasks. In recognition of these benefits, gCF defines a framework for task definition and management that builds upon a standardisation of tasks as gCube handlers.

Overview

The handler framework is defined by the inheritance hierarchy contained in the package org.gcube.common.core.utils.handlers:

Handlers.jpg

The high-level roles of package components are summarised below:

  • GCUBEIHandler: the interface of all handlers.
  • GCUBEHandler: the abstract base implementation of GCUBEIHandler.
  • GCUBEComplexHandler: an abstract specialisation of GCUBEHandler for complex handlers, i.e handlers that manage other handlers.
  • GCUBEScheduledHandler: a concrete specialisation of GCUBEComplexHandler for handlers that schedule the execution of other handlers.
  • GCUBESequentialHandler: a concrete specialisation of GCUBEComplexHandler for handlers that chain the execution of other handlers.
  • GCUBEHandlerConnector: a concrete specialisation of GCUBEHandler for handlers that connect the inputs and outputs of handlers chained by a GCUBEScheduledHandler.
  • GCUBEParallelHandler: a concrete specialisation of GCUBEComplexHandler for handlers that parallelise the execution of other handlers.
  • GCUBEServiceHandler: an abstract specialisation of GCUBEHandler for handlers that engage in interactions with remote service port-types.
  • GCUBEStatefulServiceHandler: an abstract specialisation of GCUBEServiceHandler for handlers that engage in interactions with remote WS-Resources.
  • GCUBEStagingServiceHandler: an abstract specialisation of GCUBEStatefulServiceHandler for handlers that can stage the WS-resource with which they need to interact.

The framework also includes the following auxiliary packages:

  • handlers.events: a package of components related to the management of events produced by handlers.
  • handlers.lifetime: a package of components related to the management of the lifetime of handlers.

Basics Concepts

The basic behaviour of all handlers is defined by the GCUBEIHandler interface. The class GCUBEHandler provides a base implementation for it which most handlers are expected to directly or indirectly extend.

class MyHandler extends GCUBEHandler {

...

}

The first and foremost method of all handlers is the run() method, which implements the task associated with the handler. This is in fact the only method of GCUBEIHandler that GCUBEHandler does not implement. The following is thus one of the simplest handlers:

class MyHandler extends GCUBEHandler {

 /** {@inheritDoc} **/
 public void run() throws Exception {
   System.out.println("carrying out a task..");
 }

}

...

MyHandler handler;
...
handler.run();

Note: The framework makes no assumption about how run() is implemented, expect for the fact that it may generate an exception. For some handlers it may block while for others it may return immediately. Again, for some handlers it may be invoked only once while for others it may be invoke an arbitrary number of times.

Most handlers will need inputs and produce outputs. Since run() does not cater for them, handlers need some form of state in which clients can put inputs and find outputs. Handlers are free to define any form of state and access to state (dedicated getters, setters, and constructors). The two forms of state discussed next, however, are predefined in GCUBEIHandler to enable generic state management strategies across handlers of different types. Their use is entirely optional.

The Handled Object

The first form of state is an arbitrary object upon or on behalf of which the handler is expected to execute, the handled object. GCUBEIHandler defines accessors for it and GCUBEHandler implements them (setHandled(), getHandled()). GCUBEIHandler and GCUBEHandler are in fact parametric in the type of the handled object:

public interface GCUBEHandler<T> {
 ...
 public void setHandled(T h);
 public T getHandled(T h);
 ...
}

Note: The parametrisation allows the framework to be specialised in contexts where handlers are expected to handle objects of a give type, at no loss of static typechecking.

In spite of their name, not all handlers need a handler object of course. MyHandler above does not for example and derives GCUBEHandler as a raw type. To avoid compiler's warnings, it could have been defined as:

class MyHandler extends GCUBEHandler<Object> {...}

The following variation of MyHandler exemplifies the use of handled objects:

class MyHandler extends GCUBEHandler<String> {

 /** {@inheritDoc} **/
 public void run() throws Exception {
   System.out.println("executing with "+this.getHandled());
 }

}

...

MyHandler handler;
...
handled.setHandled("some task");
handled.run();

Note: In practice, the handled object is often an instance of some distinguished component of the service implementation (e.g. a stateful resource). One ore more handlers are then used to implement tasks associated with the instance as if they were separate extensions of its class:

class SomeServiceComponent {.....}
...
class SomeComponentTask extends GCUBEHandler<SomeServiceComponent> {

 /** {@inheritDoc} **/
 public void run() throws Exception {
    ...
    ... this.getHandled().getSomeProperty()...
    ... // do something important .....
    ... this.getHandled().setSomeOtherProperty(...)...
    ... 
 }

}

Note: For convenience, GCUBEHandler has a constructor parametric in the handled object to which subclasses may wish to delegate.

class MyHandler extends GCUBEHandler<String> {

 public MyHandler(String s) {super(s);}
 ....

}

The Blackboard

A less constrained form of state associated with all handlers is in the forms of a map of arbitrary named objects, the blackboard. Again, GCUBEIHandler defines accessors for it GCUBEHandler implements them (getBlackboard(), setBlackboard()). The names of the objects that handlers expect to find in their state or else put in their state is defined by the convention (i.e. it must be part in the documentation of the handler).

class MyHandler extends GCUBEHandler<Object> {

 /** {@inheritDoc} **/
 public void run() throws Exception {
   this.getBlackboard().put("output",this.getBlackboard().get("input")+1);
 }

}

...

MyHandler handler;
...
Map<String,Object> map = new HashMap<String,Object>();
map.put("input",5);
handler.setBlackboard(map);
handler.run();
System.out.println(handler.getBlackboard().get("output"));

This exemplifies the use of the blackboard but does not justify it. The blackboard is intended primarily for the loosely-coupled exchange of information between handlers that are developed independently but under the same conventions (rather than for the exchange of information between handlers and their clients). As we discuss below, this exchange may occur when handlers are chained in a GCUBESequentialHandler.

Auxiliary Functionality

[coming soon]

General-Purpose Handlers

[coming soon]

Sequential Handlers

[coming soon]

Parallel Handlers

[coming soon]

Scheduling Handlers

[coming soon]

Handlers for remote Interactions

[coming soon]

Service Handlers & the Client Interface

[coming soon]

Staging Service Handlers

[coming soon]