The refcodes-jobbus artifact makes use of the command pattern and provides a
frame to work with commands (jobs) also in a distributed environment (e.g.
REST, SOA, Cloud Computing) and provides do/undo functionality.
The terms "command" and "job" are used interchangeably. To understand the
benefits which the job-bus offers, we should briefly understand the command
pattern. Below I will describe the command pattern in the context of the
job-bus; which might differ slightly from the command pattern as described in
literature.
Simply speaking, you push a job into your job-bus. You can either wait for
the job to be executed and grab its result when done or you us a handle to
grab the result later on. The job is being executed asynchronously, it is up
to the job-bus where and when it is being executed: For example the job could
be transported to some remote JVM to be executed there or the job could get
executed as soon as a worker thread is happy to grab the job from a
job-queue.
Command (Job):
A command (job) represents an (atomic) operation applied to a context
encapsulated in an object (as of object oriented programming). Usually a
command also provides means to undo its operation applied before. The command
is created by a client (e.g. the business logic) and passed to the job-bus
for execution.
Client:
The client may be the business logic creating a command (job) to be executed.
Context:
The context can be a service, a service-bus (providing a handful of
services), a component or a plain POJO (this depends on your requirements and
your implementation).
Job-Bus:
The job-bus takes a client's command (job) to be executed. For asynchronous
execution a handle is passed back to the client with which the state (in
progress, failure, success) of the command (job) can be determined as well as
the command's (job's) result be requested (the actual result or an exception
in case of failure). For synchronous operation, the job-bus halts your
invoking thread till either the result is (available and) passed back or an
exception is thrown.
To invoke a command (job), the job-bus, being the invoker, passes the context
to the command (job) and requests the command (job) to apply its operation
with regard to the context.
As you can see, the job-bus is responsible for managing the context and for
invoking the command (job). This decouples the business logic from the
knowledge on how to retrieve a context or where the command is actually being
executed (more on this later).
As of the implemented handle paradigm, the job-bus may be used by various
parties without revealing their command (job) instances (to each other) being
processed by the job-bus.
Job-Bus directory:
The job-bus directory is actually a plain extension of the job-bus providing
access to all the handles currently being managed by the job-bus. The job-bus
directory provides means to get a full listing of currently known
Command
(job) instances and the according handles. Only privileged
systems should access the job-bus directory as any system having access can
intervene with the
Command
(job) instances without owning those
Command
(job) instances (without owning the according handle).
Distributed environment:
The operation a command (job) represents is atomic, encapsulated in an object
and applied to a context. The job-bus may distribute the command (job) to a
different job-bus, probably located on a different machine, where the command
(job) eventually gets executed. The result of the command (job) execution
then gets passed back to the originating job-bus, which then passes it back
to the client.
(this scenario assumes that a) your command (job) is serializable as well as
b) your result is serializable)
Do-/Undo-Stack:
As a command (job) may also undo things it has done (executed), an undo stack
may hold your application's command (job) instances in the order of their
execution. Using to undo stack in reverse order, the executed operations can
be undone one-by-one or in batch.
Component / Service:
In a component or service driven environment, the job-bus may be one of the
services centrally being set up and configured as well as centrally being
provided to your application's component (service) instances. So you have one
point of command (job) execution; application wide; providing the benefits of
the job-bus in a transparent manner to your application.