System Architecture

This document provides an overview of the bexee system architecture, hoping to give a better understanding of its general design.

As opposed to the Engine Architecture or Solution Description documents, which specifically document individual parts of bexee, the System Architecture document focuses on the architecture of the entire application, and hence tries to give a general overview of the whole system.

  1. Deliverable structure
  2. Axis Integration
  3. Process Deployment
  4. Process Execution
  5. Persistence
  6. bexee WebApp

Deliverable structure

bexee runs in a servlet container e.g. Apache Tomcat and thus ships ready to use in a web application archive (war) file. The war is divided into a number of components according to function that make up the entire application.

The accompanying illustration gives a rough overview of the main components that belong to bexee:

Engine Core

We will start from the inside out, explaining what the different components do and thus begin with the Engine Core component.

The Engine Core comprises all the business logic and knowledge about how to process a given BPEL document.

Most importantly this includes the BPELProcessFactory for creating a BPEL process given a BPEL document, the ProcessController for processing a BPEL process, the Dispatcher for looking up deployed BPEL processes and executing instances as well as a number of other components.

As the name implies this is the core of the bexee engine, but of course there is a number of other supporting components that are needed, for making bexee a complete application.

Provider

The provider has a key role in bexee, because it is responsible for connecting Axis and bexee. How this works exactly will be explained further down in this document in the Providers section.

Management

The Management component includes classes for deploying new BPEL processes to bexee and registering them as Web Services in Axis. It is foreseen that in a later release, there will also be some classes that can be used to administrate the engine.

It is important to note that management components are deployed as Web Services into Axis. This allows for an open interface available to a number of various clients; e.g. web application front-ends, Ant tasks, etc. (see Ant Tasks section)

Axis

As explained in the previous section we are using Apache Axis for processing SOAP messages. The Management and Engine Core components are deployed into Axis as Web Services.

WebApp

The WebApp component includes Servlets, JSP's, HTML pages etc. offering more convenient access for querying or managing the engine. As shown in the deliverable structure diagram further up in this document, you can see that the engine is always accessed through its Web Service interfaces; be it for deploying or executing. More detailed information on this component can be found in the bexee WebApp section further down in this document.

Axis Integration

The Axis framework is a Java-based, open source implementation of the SOAP specification from the Apache Group. Essentially Axis is a SOAP engine, i.e. a framework for constructing SOAP processors such as clients, servers, gateways, etc.

Axis provides a flexible messaging framework that includes handlers, chain, serializers, and deserializers. The latter provide encoding support for a wide variety of XML Schema data types.

In the following sections we will describe how we extended, used and integrated Axis in bexee. It is assumed that the reader has a basic understanding of the Axis architecture and how Axis works. More information on the Axis project can be found on the Apache Axis web site [Axis].

The need for Axis

Every BPEL process has to expose itself as a Web Service in order to be triggered by clients who want to execute the process. We thus need to process incoming Web Service request, i.e. SOAP messages, transfer the request to the bexee engine for processing and after the process has finished executing, send a SOAP message containing the process result back to the client.

This led us to the decision to use Apache Axis for processing SOAP messages.

Providers

A provider is a special Axis Handler which handles incoming requests. Axis makes available a number of different providers. A JavaProvider for example handles a request by invoking a method on a given Java class and then returns the result back to the response flow. Usually this is the default behavior for Web Services deployed in Axis.

Which provider shall be used for a given Web Service can be specified upon deploying a new service. Axis' provider model is extensible, which means that you can plug in your own custom providers. Below you find a typical wsdd file used for deploying services into Axis. The service will be accessible under the name bexeeService and incoming requests will be handled by a custom provider.

Note that in Axis, providers are sometimes also refered to as pivot handlers.

<deployment xmlns="http://xml.apache.org/axis/wsdd/"
            xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
  <service name="bexeeService" provider="java:BexeeProvider" />
</deployment>

As the above deployment descriptor shows, we use a special provider called BexeeProvider, which we plug into the Axis engine. Strictly speaking it is not the provider itself that is plugged into Axis, but rather a custom factory which will then create the provider of the given type.

Below you find an excerpt of the factory and provider class together with the methods they implement:

BexeeWSDDProvider
public class BexeeWSDDProvider extends WSDDProvider {

    public Handler newProviderInstance(WSDDService service,
            EngineConfiguration registry) throws Exception {

        return new BexeeProvider();
    }

    public String getName() {
        return "BexeeProvider";
    }
}
BexeeProvider
public class BexeeProvider extends BasicProvider {

    public void initServiceDesc(SOAPService service, MessageContext msgContext)
            throws AxisFault {
        // init the service
    }

    public void invoke(MessageContext ctx) throws AxisFault {
        // process message and invoke target service
    }

    public void generateWSDL(MessageContext msgContext) throws AxisFault {
        // generate the web service description
    }
}

This means that we are using our own custom provider for connecting Axis and bexee: The provider takes the incoming SOAP message, performs a number of checks (e.g. verifies whether the requested operation can actually be performed by the process controller), puts all the necessary information into a new BexeeMessage and passes it to the Dispatcher, the entry point to the bexee engine.

Note that the BexeeMessage contains no SOAP specific data. This allows for a decoupling of the bexee engine and thus keeping it relatively independent from Axis and the SOAP protocol.

As soon as the provider receives the result back from the Dispatcher, it will create a new SOAP response and hand it back to the Axis response flow, from where it will eventually be sent back to the client that invoked the service.

The following illustration shows the connection between Axis and bexee. If you've read the Axis architecture guide you may notice that we've simply replaced the provider on the left side of the picture with our own BexeeProvider.

For an explanation of what happens after a new BexeeMessage arrives at the Dispatcher refer to section Dispatching incoming messages in the Sequence Diagrams section of the Solution Description.

EngineConfigurationFactory

EngineConfigurationFactory is an interface used to construct concrete EngineConfigurationFactory instances.

public interface EngineConfigurationFactory {
    public EngineConfiguration getClientEngineConfig();
    public EngineConfiguration getServerEngineConfig();
}

Each EngineConfigurationFactory implementation must also (directly) implement the following static method:

public static EngineConfigurationFactory newFactory(Object param);

Which engine configuration is to be used can be specified with either a system property or using Jakarta Commons Discovery [Discovery]. In bexee the later approach has been used. As to enable the Discovery mechanism a file called org.apache.axis.EngineConfigurationFactory must be created in the META- INF/services directory in bexee.jar. Inside this file the fully qualified name of the class implementing the EngineConfigurationFactory must be indicated.

Plugging our own BexeeEngineConfigurationFactory into Axis allows us to specify how the Axis server will be configured when it is created.

We use this technique to make the bexee Manager Web Service available as soon as a new Axis server is created. For more information on this please refer to Deployment section further down in this document.

The BexeeEngineConfigurationFactory extends the EngineConfigurationFactoryServlet in package org.apache.axis.configuration and basically doesn't do anything else but making sure that the right server configuration file is read in, when a new factory is created. The server configuration file is stored as a wsdd file and includes - among other things - the following service deployment information for deploying the Manager Service.

<service name="Manager" provider="java:RPC">
  <parameter name="allowedMethods" value="*"/>
  <parameter name="className" value="bexee.admin.Manager"/>
</service>

The initial configuration is read from a default configuration file, which is called bexee-config.wsdd and is packaged into the war file. Modified configurations will be stored inside the WEB-INF directory of the deployed bexee web application.

Process Deployment

Hot-Deployment

A design goal of bexee is to be easy to use in order to make it interesting for experiments with business processes and BPEL in general. We therefore decided to provide a hot-deployment mechanism in bexee. The main idea of such a mechanism is to ensure a simple way for the users to deploy business processes in bexee without requiring to have knowledge of the internal mechanisms of bexee. It will only be necessary for the user to describe the business process in BPEL and the necessary Web Service Descriptions (WSDL). The user then deploys these files to bexee and the process will be implemented as a Web Service and will be made available to be used by clients.

The contrary to such a hot-deployment mechanism would be requiring a user to generate Java code for invokation of partner Web Services and Web Service stubs for the invokation of the own Web Service interface (as for all Receive BPEL activities), to compile generated code, package it and add it to the bexee classpath.

In our opinion an important purpose of the BPEL standard is to provide a language for business process modelling which is abstract enough to make it unnecessary for the modeller to know a programming languages like Java. The business process modeller needs certainly to have a good knowledge of the BPEL language, XPath and Web Services, but should not need to worry about how exactly the modeled processes will be represented or executed within a BPEL engine.

The main purpose of a hot-deployment mechanism is to shield the user from the implementation details of bexee. Providing a hot-deployment mechanism removes the necessity for a user to have an in-depth knowledge of technology specific aspects and maintains the advantages of decoupling the BPEL standard from the underlying technologies.

How it works

In order to deploy a business process, a number of documents are needed. The user has to prepare the BPEL document describing the process flow as well as define a WSDL document, specifying the process' Web Service interface. If other Web Services are to be invoked by the process, which of course is usually the case, the user also needs to provide the WSDL files of those partner services, possibly enriched with partner link information.

bexee provides a simple Manager Web Service which can be used to deploy the prepared documents. The Manager Web Service is responsible for deploying new BPEL processes to bexee and deploying them as Web Services to Axis.

Making the Manager Web Service available at Axis bootstrapping-time allows to use it as soon as bexee is deployed into the servlet container, i.e. Tomcat.

In this and the next section we will interchangeably refer to the deployed BPEL process either with BPEL process or BPEL service, depending which one is more appropriate in the context we are talking.

  1. As already indicated above, alongside with the BPEL document itself, the user also needs to provide a Web Service descriptions (WSDL) for the process and all the partner Web Services. As soon as the user has collected or created all the necessary documents, he can send them to the Manager Web Service.

  2. The Manager Web Service will create use a factory to create a new BPELProcess object, given the input of the BPEL document the user provided. At the same time the input will also be validated against syntactic errors.

  3. Then another factory is used to parse the WSDL input documents, that is the WSDL describing the BPEL service as well as the WSDL documents describing the partner services. Again the input will be validated against syntactic errors.

  4. The next step is to extract the necessary information out of the process' WSDL so that an Axis deployment descriptor can be created.

    Once this has been done, the service will be deployed as a Web Service by adding it to the Axis engine configuration.

  5. Finally, the BPEL and WSDL document object representations will be persisted to a data source. For that purpose the Manager uses bexee's Data Access Objects (DAOs) (see Persistence).

  6. At the end, a response about the successful deployment will be send back to the user.

As already mentioned above, the modified Axis configuration will be stored inside the WEB-INF directory of the deployed bexee web application.

As explained in the Hot-Deployment section, new BPEL processes will be deployed as Web Services into Axis at run- time. This means that as soon as the Manager has finished deploying a new BPEL process, it will immediately be available as a Web Service available for clients to use.

Process Execution

This section documents how a BPEL process that has been previously deployed to bexee (see section Deployment above) is executed inside bexee.

As already mentioned, deploying a BPEL process means also that the process will be implemented and exposed as a Web Service, according to the WSDL file that describes the Web Service interface of the process. The beauty of this is that a user can use this service just like any other service that is described in WSDL. The user doesn't necessarily need to know that the service she is using, basically is nothing else but a composition of existing services.

We will now describe, based on the following illustration, what happens inside bexee when a client invokes a deployed BPEL process or service to be precise.

The illustration and explanation relate to a synchronous BPEL process. For asynchronous processes the execution flow is very similar, except that the ProcessController doesn't return the result back to the client, but rather sends the result by invoking a call back Web Service that has been provided upon deployment.

  1. A client remotely invokes the deployed BPEL service. Because the service is described in WSDL a client can obtain information about the process (e.g. which operations can be executed) in a standardized manner.

  2. The incoming SOAP message is processed by Axis (not shown in illustration) and after running through all the Axis request handlers, eventually arrives at the BexeeProvider which is an (Axis) provider or pivot handler and responsible for connecting Axis with bexee (see Providers in Axis Integration section).

  3. The BexeeProvider first performs a number of checks (e.g. operation existence / signature) and then disassembles the incoming SOAP message in order to create a new BexeeMessage. Using our own independent message object allows for a decoupling of the bexee engine and thus keeping it relatively independent from Axis and the SOAP protocol. Once the BexeeMessage has been created and filled in with all the necessary values, it is send to the Dispatcher.

  4. The Dispatcher looks up the DAOs for a matching BPELProcess and ProcessContext given the information in the received BexeeMessage. If no ProcessContext can be found (e.g. it is the first time that a client invokes a service and thus has no running process yet) a new ProcessContext will be created. After that the Dispatcher will dispatch the message together with the process and context to the ProcessController. This will either happen synchronously or asynchronously, depending wheter the deployed process is synchronous or asynchronous.

  5. Once the ProcessController has received the necessary input, it uses the Visitor pattern (see [Gamma95]) to start processing the activities defined in the deployed process.

  6. The main purpose of BPEL is to integrate existing Web Services ant thus probably every meaningful BPEL process will at some point use existing external Web Services, which will be invoked by the ProcessController.

  7. After the ProcessController has terminated its execution it will return control to the Dispatcher. Terminating execution can mean two things here: Either the ProcessController terminates, because it has reached the end of the deployed BPEL process and there are no more activities to process or the controller reached a point in the process, where more input from external sources is needed (e.g. user input or input from asynchronously invoked partner services).

  8. Depending wheter a result is available or more input is necessary, the Dispatcher will either wait for more input messages and proceed as in the previously described steps or it will get the result and return it back to the BexeeProvider.

  9. The BexeeProvider takes the result and packs it into a SOAP message, which will be given over to the Axis response flow.

  10. Once the message has passed all the Axis response handlers, it will be sent back to the client.

Persistence

The Dispatcher dispatches inbound messages to the correct process instances and thus has to maintain a store for them. A ProcessInstance is composed of a BPELProcess and a ProcessContext. Whereas there exists only one instance of the BPELProcess per deployed BPEL process, there exists a multitude of ProcessContext instances, as new ProcessContexts are created for each client that starts a process. Hence it makes sense to store the two objects separately.

Data Access Object (DAO) pattern

bexee uses the Data Access Object (DAO) pattern to encapsulate all access to the BPELProcess and ProcessContext by providing a DAO for each one of them. The DAO manages the connection with the data source to obtain and store data.

The DAO implements the access mechanism required to work with the data source. The data source could be a persistent store like an RDBMS, a File System or any other data source you can think of. The components that rely on the DAO use the simpler interface exposed by the DAO. The DAO completely hides the data source implementation details from its clients. Because the interface exposed by the DAO to clients does not change when the underlying data source implementation changes, this pattern allows the DAO to adapt to different storage schemes without affecting its clients or business components. Essentially, the DAO acts as an adapter between the component and the data source.

Memory DAOs and Abstract Factory Pattern

In the current version of bexee only an in-memory DAO is provided. In- memory means that data is only stored in memory and hence lost on server restarts etc.

Obviously this might not be enough for most applications and thus bexee provides the flexibility of adding new DAO implementations at a later time without having to modify code. (For an example on how a JDO DAO implementation could be added, refer to the Implementing DAOs section in the Developer's Guide).

This flexibility is achieved by using the Abstract Factory pattern as suggested in 'Design Patterns - Elements of Reusable Object-Oriented Software' [Gamma95].

In this case, an abstract DAO factory object (Abstract Factory) is provided, which can construct various types of concrete DAO factories, each factory supporting a different type of persistent storage implementation. Once you obtain the concrete DAO factory for a specific implementation, you use it to produce DAOs supported and implemented in that implementation.

The class diagram for the currently implemented DAOs in bexee shows a base DAO factory (DAOFactory), which is an abstract class that is inherited and implemented by different concrete DAO factories to support storage implementation-specific access.

The client can obtain a concrete DAO factory (e.g. MemoryDAOFactory) by calling the DAO factory's getInstance() method. Which DAOFactory implementation will be returned, is determined by an application or system property (bexee.dao.factory) specifying the fully qualified class name of the DAOFactory implementation to be used.

If you are interested in extending the model and writing your own store implementation, take at look at the Implementing DAOs section in the Developer's Guide.

For more information on the DAO pattern, please refer to Sun's Core J2EE Patterns catalog [J2EEPatterns].

bexee WebApp

Probably the most important component in the web application is the AxisServlet which was shamelessly copied from the Axis web application and handles all the Web Service traffic for bexee.

The routing of an incoming http request containing a SOAP message is handled by the AxisServlet, which runs inside the bexee web application. It is the main entry point for every incoming Web Service request. The URL pattern that will invoke the AxisServlet is configured to /bexee/services/*.

The AxisServlet's duty is to take on incoming http requests, process them and deliver them to the Axis engine, which will finally invoke the target service or the provider to be more precise.

The AxisServlet is also responsible for creating a new AxisServer in case one has not already been created. To do this, the AxisServlet uses an EngineConfiguratinoFactory as described above and then uses this information to create a new AxisServer with the help of a an AxisServerFactory.

The AxisServer is only created once by the AxisServlet during the life time of the web application. This is done upon the first request to the AxisServlet and the AxisServer is then put in to the web application context from where it will be retrieved for every subsequent request.