The InstantSOAP architecture aims to ballance the following qualities:
These concerns are addressed by the InstantSOAP architecture in two ways. Performance, resource and scaling concerns are handled by minimising per-invocation object instantiation within the dispatch stack, and by using threaded job queues. Configurability and modularity are ensured by using multiple, fine-grained maven modules, each providing APIs or implementation code for a single defined task. Concrete implementations of these APIs are then aggregated at run-time into a fully configured graph of objects; there are no constructor calls to concrete classes present anywhere in the Java codebase itself.
The major components involved in processing a client request are: the client; the webservice or web application container hosting InstantSOAP; the SOAP library that handles the messaging; the InstantSOAP dispatch stack; and the business logic.
The client is any software component capable of using SOAP over HTTP. This may be acting directly as an agent for a user (for example, embedded in a web page or GUI) or for another software agent (for example, part of a workflow). The client will innitiate an interaction with an InstantSOAP deployment by SOAP messaging the deployment's URL.
The webservice container is responsible for managing an HTTP server and routing requests for specific URLs on to the components that will handle them. The container manages the lifecycle of all the components it contains, creating instances as required and performing load ballancing, fail over and other dependebility functions. When the client contacts the InstantSOAP deployment's URL, the web service container will recieve this, do any HTTP-specific handling that is required and then hand this off to the SOAP library.
The SOAP library is responsible for mapping between the HTTP protocol and objects representing SOAP messages. It is also responsible for routing these messages through to the Java service objects that will do the actual handling. When the SOAP library recieves a HTTP message from the webservice container, it will parse it from XML, build InstantSOAP request objects and invoke the right method of the InstantSOAP service object.
The InstantSOAP dispatcher recieves requests for describing and running applications. It manages resources corresponding to result files, maintains queues of pending jobs, and decouples the asynchronous or synchronous invocation semantics exposed to the client from the strategy used internally. When the SOAP library invokes the InstantSOAP service object, this passes control directly to the dispatcher. This then validates the request and enqueues it. The request is then dequeued by a different thread, and is passed on to the business logic that will handle this particular request.
The buisness logic is the actual work that is done to generate responses. This may execute some Java code, a native application or invoke an interpreter to support code in any language. When the dispatcher passes control to the business logic, it generates the response and returns this to the dispatcher.
None of these components need know any of the specifics about how their neighbours work. They exclusively communicate through their APIs. This provides great flexibility in how the system can be deployed, and allows one component to be replaced or updated without other components being affected.
The dispatch stack is where people deploying InstantSOAP can inject custom policies for managing request processing. This section disusses the upper and lower tier of the dispatch stack, and describes some of the more important classes and interfaces involved. The upper tier of the stack is responsible for bridging the service oriented architecture exposed as a web service to an object-oriented architecture used for implementation. The lower tier of the stack is responsible for managing the invocation of business logic, and in particular, for decoupling the flow of control in the business logic from that in the dispatch stack. These two tiers are discussed more fully in the following subsections.
The web service interface for InstantSOAP is
WebServiceDispatcher
. This provides one method to
list the names of all applications that the installation can handle,
methods for describing applications and their inputs and outputs given
the appilcation name, and methods for invoking an application in
blocking (synchronous) or non-blocking (asynchronous) modes.
The standard implementation of this interface does the minimal work needed to bridge from a service-based invocation style to the standard models used when programming Java. It then delegates all of the work on to synhronous and synchronous service dispatchers.
The service dispatcher classes provided by InstantSOAP pass control on
to an object implementing the
StrategyDispatcher
interface. The strategy dispatcher
level is responsible for ensuring that the correct buisness logic handles
each request, and that the control flow of the buisness logic is decoupled
from the controll flow of the incomming requests.
Executing a job specification using a strategy dispatcher is a two
stage process, validation followed by invocation. Validation is
initiated when the invoker calls the
validateJob(JobSpecification)
method on the dispatcher.
This method will firstly validate the job. If the job is clearly
going to fail then this can be reported emediatelly, avoiding tieing
resources up further down stream. If the job passes the validation
test, then the dispatcher creates a
ValidatedJob
that can be used to launch the job.
Invocation is initiated by the client calling dispatch()
on the validated job. This returns a UUID
that uniquely
identifies this invocation, and starts the process of launching the
buisness logic associated with the job. The same validated job
can be dispatched any number of times, and each time a new UUID
will be returned.
The dispatch()
method takes a listener. This is the object
that will be informed as the buisness logic is actually executed. It has
a method to indicate that the job has started, that it has completed
successfully, and that it has completed with failure. Any or all of these
methods may be invoked at any time, both during and after the dispatch()
method has returned control to the invoker, and both in the same or a
different thread. The client should make no assumptions about any of
these possibilites.
The underlying execution system can process tasks at a rate dictated by
the available hardware. Incomming requests may arrive faster or slower than
this rate. Inserting a queue between the incomming requests and the
job handling allows load to be handled more evenly. The
QueuedDispatcher
class provides an implementation of
the dispatcher interface that enqueues jobs when dispatch
is
invoked, and processes the queue using a threadpool.
Several different dispatchers may be responsible for handling different
applications. The
MultiplexingStrategyDispatcher
class provides an implementation
of strategy dispatcher that sends requests on to other dispatchers.
It maintains a set of dispatchers. Incomming requests are matched against each of
these in turn, untill a nested dispatcher that can handle the request is found.
The request is then forwarded on to this dispatcher for further processing.
This affords developers of business logic quite a degree of latitude about how
individual kinds of applications are presented to the system.
Exposing the business logic itelf is achieved by providing an implementation of
strategy dispatcher that performs the required task when dispatch
is invoked. The InstantSOAP codebase provides one such implementation,
MapStrategyDispatcher
. If you wish to develop a new
binding for InstantSOAP, you can either write a new dispatcher implementation,
or instead expose it directly as an object that MapStrategyDispatcher
can expose. There are arguments to be made for both approaches.