Version 1

    Serveral times in the System Integration Field when we are dealing external system (System To System) calls (1) we don't want to block(2) the caller until the remote service process and send us back the results (3).

     

    no-executor.png

     

    In the context of business processes, we need to deal with this kind of situations regularly, and there is a strong need to be able to delegate a System Call to a decoupled component that will be in charge of handling the required System Call for us to not block our Business Process Engine execution. For long running persistent timers we have a similar situation:

     

    no-executor-timer.png

    We have a business timer, which can be scheduled to due in 48hs. Technically we need to keep a thread for that specific timer in order to call a specific system as soon as it due. The thread that is in charge of monitoring the Timer will be also in charge of calling System 1 in this case and it will block until System 1 returns the results for that call. The application containing the timer, is just another application, but in this case, instead of wanting to call System 1 inmediately there will be a span of time that needs to be waited in order to do the external system call.

     

     

     

    Generally speaking, The Executor Componentneeds to be able to receive requests to schedule asynchronous tasks executions (as soon as possible or derefered in time). In some way, this component will be exposed as a service. It will need to be available to the requester  -- it could be a remote client or a direct (in jvm) reference. Once this component receives and acknowledges the request, it needs to have a way to pick a request (from a request inbox or list) and then execute that request. Usually, this mechanism contains retrying mechanisms as well as an exception handling mechanism that allows us to recover the execution if something fails with the external application (for example, if it’s not available at a particular point in time). This component must have a way of contacting the requester back to notify it when the execution is done. To do this, the component usually stores a business key that allows us to achieve the notification successfully.

     

    executor-simple-steps.png

    From the (any) application point of view, the executor component is just another service that we can use in order to delegate executions. Instead of interacting directly with another applications we will use the Executor Component as an Intermediary that will allow us to handle all our external interactions asynchronously. Besides this important feature there are another important things that the executor component can do for us:

    1. Derefered Executions: if our application needs to wait for long period of time in order to execute a task, we can delegate that responsability to the executor component.
    2. Retry Mechanism: If a scheduled job cannot contact the external system, we can configure a number of retries for each particular job.
    3. Generic Exception Handling: Based on the expcetions reported by the external system, we can automatically decide if we want to retry or if we want to call another service instead
    4. Administrator Queue: If all the retrying mechanism fails several times or if we have a failed execution that cannot be retried, a task can be created for the administrator to fix the problem, correct the environment and retry the job manually. 

     

    This executor service will use the Command Pattern (http://en.wikipedia.org/wiki/Command_pattern) in order to schedule remote executions. These commands will contain the logic that needs to be executed, allowing us to create new commands if we have special requirements

    .

    The Executor Service just exposes two methods:

    public interface Executor extends Service{

        public String scheduleRequest(String commandName,  CommandContext ctx);

        public void cancelRequest(String requestId);

    }

     

    The scheduleRequest method will receive the name of the command that we want to schedule and a CommandContext, contain among another things the business key that we can use to make reference to this particular execution, that will be used to gather all the information required to execute the request.

    In order to use this service we will need to configure it accordingly based on our business requirements. For some scenarios we need a service that this component monitors the list of request all the time and we have not urgent tasks that can wait to be executed, for example twice a day.

    The executor service will be running as a separate component of our application and it will need to be initialized when we know that another component will be trying to schedule new requests to be executed.

     

    Different implementations for this interface can be provided depending on the environments where we are planning to deploy the component.

    One important thing is that multiple Executor Component instances can be instantiated and configured to work with different configurations in the same environment, providing us an scalable way to support several concurrent request executions.

     

    The following link points to a PoC of this component, based on CDI/Weld and Seam Persistence & Transactions, in the same way that the new Human Task Service module is working. Providing a simple implementation for SE environments using a Database as a BackEnd. More advanced implementations using MDBs can be provided for working in EE environments.

    https://github.com/Salaboy/human-task-poc-proposal/tree/master/executor-service