OverviewOSWorkflow can be easily integrated into any ligthweight container, such as Spring, XWork or NanoContainer. The advantage of doing so is that for users of these frameworks, osworkflow can easily be hooked into the container facilities for dependency resolution, component wiring, and lifecycle management. Out of the box the OSWorkflow distribution contains the integration with the Spring Framework, through the following components: 1) SpringHibernateWorkflowStore to let the workflow instances participate (if desired) to the current transaction. 2) SpringTypeResolver to allow osworkflow to obtain business logic components (conditions, functions, and so on) from the Spring ApplicationContext. 3) SpringConfiguration which is an implementation of the Workflow Configuration interface that contains references to the store and to the factory, thus enabling the container to inject and wire them. 4) SpringWorkflowFactory which is a wrapper of the XMLWorkflowFactory that allows the injection of the configuration from the container, instead of reading them from another XML configuration file. These four elements ensure that osworkflow can be tightly integrated into the Spring Framework. Example UsageThe following is a step by step example usage of performing this integration, through creating the osworkflow-spring.xml configuration file. This file is written as a child ApplicationContext of another that must contain the hibernate sessionFactory configuration. First the persistent store for the workflow instances must be define, as well as the factory that reads the finite state machine: <bean id="workflowStore" class="com.opensymphony.workflow.spi.hibernate.SpringHibernateWorkflowStore"> <property name="sessionFactory"><ref bean="sessionFactory"/></property> <!-- Optional PropertySet delegate, in case you want to use another PropertySet store that is not HibernateStore <property name="propertySetDelegate"> <ref local="propertySetDelegate"/> </property> --> </bean> <bean id="workflowFactory" class="com.opensymphony.workflow.loader.SpringWorkflowFactory" init-method="init"> <property name="resource"><value>workflows.xml</value></property> <property name="reload"><value>true</value></property> </bean> having defined these two beans we can define the workflow Configuration object; <bean id="osworkflowConfiguration" class="com.opensymphony.workflow.config.SpringConfiguration"> <property name="store"><ref local="workflowStore"/></property> <property name="factory"><ref local="workflowFactory"/></property> </bean> and then, if required, the SpringTypeResolver, to allow OSWorkflow to utilise spring managed beans for business logic: <bean id="workflowTypeResolver" class="com.opensymphony.workflow.util.SpringTypeResolver"> <!-- Here you can inject custom resolver for business logic <property name="conditions"> <map> <entry key="beanshell"> <value>mypackage.MyBeanShellCustomCondition</value></entry> </map> </property> --> </bean> If no interception is required, then the file is now complete, and OSWorkflow can be used with Spring. <bean id="workflow" class="com.opensymphony.workflow.basic.BasicWorkflow" singleton="false"> <property name="configuration"> <ref local="osworkflowConfiguration"/> </property> <property name="resolver"> <ref local="workflowTypeResolver"/> </property> </bean> On the other hand, if a transactional wrapper is required, or AOP type functionality, then we can decorate the workflow instance. For the purposes of this example, we will add an interceptor for workflow methods. So the last bean definition should be substituted with the following: <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager"><ref local="transactionManager"/></property> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> <bean id="workflow" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="singleton"> <value>false</value> </property> <property name="proxyInterfaces"> <value>com.opensymphony.workflow.Workflow</value> </property> <property name="interceptorNames"> <list> <value>transactionInterceptor</value> <value>workflowTarget</value> </list> </property> </bean> <bean id="workflowTarget" class="com.opensymphony.workflow.basic.BasicWorkflow" singleton="false"> <constructor-arg><value>test</value></constructor-arg> <property name="configuration"><ref local="osworkflowConfiguration"/></property> </bean> With this definition, every method of the instance have the opportunity to be decorated by a surround aspect. Last, but not least, it is also possible to inject business functionality using the SpringTypeResolver: <bean id="myFunction" class="mypackage.MyFunction" singleton="false" /> and then use it into the OSWorkflow XML definition: <function type="spring"> <arg name="bean.name">myFunction</arg> </function> |