Skip to content

Trooper Orchestration Profile

regunathb edited this page Dec 31, 2012 · 13 revisions

The Trooper Orchestration Profile enables chaining of a number of execution stages in a manner reminiscent of workflows. Each stage is implemented as a Trooper Service (see Writing-Services-in-Trooper) and this in turn means any Trooper service can participate in a workflow, with transformation and routing implemented outside the service.

Orchestration in Trooper is defined in a XML based DSL using Mule (http://www.mulesoft.org/) as the underlying technology. Mule is embedded into the Trooper runtime using Spring DI as a light-weight object broker. Mule is therefore not used as a conventional ESB, but rather as an implementation of the SEDA architecture pattern (http://en.wikipedia.org/wiki/Staged_event-driven_architecture) for distributed parallel processing.

Maven artifacts

GroupID/Org ArtifactID/Name Description
org.trpr serviceframework-seda The Service Orchestration Profile implementation. Includes the Trooper add-ons for this profile.

SEDA (Staged Event Driven Architecture)

A diagrammatic representation of the SEDA model used by Trooper is shown below:

SEDA model

Profile characteristics

The orchestration profile provides the following to its users:

  • Provision for modular development, testing and deployment of workflows and services
  • Life-cycle management of workflows, configuration refresh using administrative console(s)
  • Compile-and-run support for all orchestration profile features - does not require any packaging for deployment and testing thereby saving development time, providing for easier debugging (via standard break-points in IDEs)
  • Implementation of Convention-Over-Configuration practices to ease development, deployment

Trooper add-ons

  • Exception routing as JMX notifications - Trooper provides an Exception handling strategy implementation (org.trpr.platform.seda.impl.mule.exceptionhandling.ServiceExceptionStrategy) that forwards error details as JMX notifications.
  • RabbitMQ transport - Trooper provides a Mule 2.x interface compliant transport implementation for RabbitMQ 2.x. See RabbitMQ-Mule-Connector
  • Service response filtering router - To filter out error service responses in the orchestration flow. Externalizes chaining logic from services, thereby making it self-contained. See org.trpr.platform.seda.impl.mule.router.ErrorResponseFilteringRouter
  • Check-pointing in workflow - Long drawn orchestrations can span time, process and machine boundaries. Check-pointing intermediate state allows for recovery from intermediate failures in stage execution. Trooper provides check-pointing API and an AOP (Aspect oriented Programming) implementation where the check-pointing data and data store can be application specific (using the Trooper Persistence-Framework). See org.trpr.platform.seda.api.checkpointing.StageExecutionEvaluator and org.trpr.platform.seda.aop.SedaStageCheckpointingInterceptor

Implement and configure a workflow/orchestration

Trooper Orchestration Profile builds on top of Mule (http://www.mulesoft.org/) and its integration with Spring. Stages, written as Services, are chained using Mule configuration files. Mule Transformer (http://www.mulesoft.org/documentation-3.2/display/MULE2USER/Using+Transformers) interface implementations translate Service Response from one Stage into Service Request for the next. Refer to the Mule Documentation for more details.

Trooper enables separation between services and stages by adopting the following approaches to configuration :

  • Services are defined as Spring beans in spring-services-config.xml. Bean id follows the naming convention : <service name>_<major version>.<minor version>
  • Service aka Stage chaining is defined in mule-config.xml using Mule XML directives. A simplified sample is shown below:
<!-- Stripped down sample Mule model demonstrating chaining of Trooper services -->
<model name="greetingModel">
    <service name="GreetingMuleService">
        <inbound>
            <inbound-endpoint ref="GreetingInputEndpoint" transformer-refs="EarthlingToGreetingServiceRequest"/>
        </inbound>
        <pooled-component
            <method-entry-point-resolver>
                <include-entry-point method="processRequest" />
            </method-entry-point-resolver>
            <!-- This bean is defined in spring-services-config.xml of this project -->
                <spring-object bean="greetingService_1.0" />
        </pooled-component>
        <outbound>
            <outbound-endpoint ref="EchoInputEndpoint"/>					
        </outbound>
    </service>
    <service name="EchoMuleService">
        <inbound>
            <inbound-endpoint ref="EchoInputEndpoint" transformer-refs="ServiceResponseToEchoServiceRequest"/>
        </inbound>
        <pooled-component>
            <method-entry-point-resolver>
                <include-entry-point method="processRequest" />
            </method-entry-point-resolver>
            <!-- This bean is defined in spring-services-config.xml of this project -->
            <spring-object bean="echoService_1.0" />
        </pooled-component>
    </service>
</model>

Testing a workflow/orchestration

Trooper workflows/orchestrations may be tested by running the Orchestration runtime profile as described under "Testing service chaining (Orchestration profile)" in Build-and-run-examples

Orchestration Examples

The Trooper examples project group contains various orchestration examples. A couple of them are described here.

Service Chaining

This sample demonstrates straightforward chaining of workflow stages defined as services. See Simple Service Chaining

Check-pointing

Checkpointing is implemented in this sample using AOP and an RDBMS provider for persistence. Relevant beans for this configuration as defined in spring-services-config.xml (Checkpointing Bean Configurations) are shown below:

<!-- AOP proxying of the service beans. Used for checkpointing stage execution status in the RDBMS -->
<bean id="serviceCheckpointingInterceptor" class="org.trpr.platform.seda.aop.SedaStageCheckpointingInterceptor">
    <property name="serviceContext" ref="serviceContext" />
    <property name="stageExecutionEvaluator" ref="greetingStageExecutionEvaluator" />
    <property name="persistenceManager" ref="greetingPersistenceManager" />
</bean>
<bean id="greetingStageExecutionEvaluator" class="org.trpr.example.seda.greeting.checkpointing.GreetingStageExecutionEvaluator"/>
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    <property name="beanNames">
        <list>
            <value>greetingService_1.0</value>	
        </list>	
    </property>
    <property name="interceptorNames">
        <list>
            <value>serviceCheckpointingInterceptor</value>
        </list>
    </property>
</bean>

<!--  The Persistence framework beans for storing check-pointing data into RDBMS -->	
<bean id="greetingCheckpointDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <property name="driverClass" value="com.mysql.jdbc.Driver" />
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/trooper" />
    <property name="user" value="test" />
    <property name="password" value="test" />
    <property name="minPoolSize" value="5" />
    <property name="maxPoolSize" value="25" />
    <property name="acquireIncrement" value="3" />
    <property name="maxIdleTime" value="60" />
    <property name="maxStatements" value="200" /> 
    <property name="idleConnectionTestPeriod" value="300" />
    <property name="testConnectionOnCheckin" value="true" />
    <property name="preferredTestQuery" value="select 1 from dual" />
</bean>
<bean id="greetingHibernateSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="greetingCheckpointDataSource" />
    <property name="mappingResources">
        <list>
            <value>packaged/hibernate/greeting/earthling.hbm.xml</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <value>
            hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
            hibernate.show_sql = false
        </value>
    </property>
</bean>	
<bean id="greetingHibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
    <property name="sessionFactory" ref="greetingHibernateSessionFactory"></property>
</bean>	
<bean id="greetingHibernateHandler" class="org.trpr.dataaccess.orm.handler.HibernateHandler">
    <property name="template" ref="greetingHibernateTemplate" />
</bean>
<bean id="greetingRdbmsProviderForHibernate" class="org.trpr.dataaccess.RDBMSProvider"
    <property name="handler" ref="greetingHibernateHandler" />
</bean>
<bean id = "persistenceDelegate" class="org.trpr.platform.core.impl.persistence.PersistenceDelegate">
</bean>	
<bean id = "greetingPersistenceManager" class="org.trpr.platform.core.impl.persistence.PersistenceManagerProvider">
    <property name="providersForEntity">
        <map>
            <entry key="org.trpr.example.seda.greeting.persistence.PersistentEarthling" value-ref="greetingRdbmsProviderForHibernate"/>
        </map>
    </property>
    <property name="persistenceDelegate" ref="persistenceDelegate"/>
</bean>