cancel
Showing results for 
Search instead for 
Did you mean: 

Running Enterprise Activiti in Websphere AS 7.0

ingo_ri
Champ in-the-making
Champ in-the-making
We have to run the activiti-engine in WebSphere, as like Daniel Meyer does it in JBoss (http://www.bpm-guide.de/2011/05/09/going-java-enterprise-with-activiti-and-jboss-as/). It is important to acces the database through a datasource and to use the transaction management of the app-server.

But Websphere differs from JBoss in accessing the Transaction-Manager. In WebSphere it is impossible to get a reference to the Transaction-Manager with jndi:

"To ensure the integrity of transaction context management (and hence the proper management of transactional resources) WebSphere Application Server does not expose the javax.transaction.TransactionManager interface to applications or application frameworks deployed into WebSphere Application Server." (http://www.ibm.com/developerworks/websphere/techjournal/0609_alcott/0609_alcott.html)

When I use this configuration:

   <!– lookup the JTA-Transaction manager –>
   <bean id="transactionManager" class="org.springframework.jndi.JndiObjectFactoryBean">
      <property name="jndiName" value="java:/TransactionManager"></property>
      <property name="resourceRef" value="true" />
   </bean>

   <!– process engine configuration –>
   <bean id="processEngineConfiguration"
      class="org.activiti.engine.impl.cfg.JtaProcessEngineConfiguration">
      <property name="dataSourceJndiName" value="java:ActivitiDS" />
      <property name="transactionManager" ref="transactionManager" />
      <property name="transactionsExternallyManaged" value="true" />
      <property name="databaseSchemaUpdate" value="drop-create" />
      
      <property name="mailServerHost" value="localhost" />
       <property name="mailServerPort" value="2525" /> 
       
   </bean>
I get this output in the Websphere console:
[06.06.11 13:06:35:858 CEST] 00000020 RemoteExcepti E   CNTR0019E: EJB threw an unexpected (non-declared) exception during invocation of method "startProcessInstanceByKey". Exception data: com.ibm.ejs.container.CreateFailureException: ; nested exception is: 
   org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'processEngineConfiguration' defined in class path resource [activiti.cfg.xml]: Cannot resolve reference to bean 'transactionManager' while setting bean property 'transactionManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in class path resource [activiti.cfg.xml]: Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: Name  not found in context "java:".

Caused by: javax.naming.NameNotFoundException: Name  not found in context "java:".
   at com.ibm.ws.naming.ipbase.NameSpace.getParentCtxInternal(NameSpace.java:1837)
   at com.ibm.ws.naming.ipbase.NameSpace.lookupInternal(NameSpace.java:1166)
   at com.ibm.ws.naming.ipbase.NameSpace.lookup(NameSpace.java:1095)
   at com.ibm.ws.naming.urlbase.UrlContextImpl.lookup(UrlContextImpl.java:1233)
   at com.ibm.ws.naming.java.javaURLContextImpl.lookup(javaURLContextImpl.java:394)
   at com.ibm.ws.naming.java.javaURLContextRoot.lookup(javaURLContextRoot.java:214)
   at com.ibm.ws.naming.java.javaURLContextRoot.lookup(javaURLContextRoot.java:154)
   at javax.naming.InitialContext.lookup(InitialContext.java:455)
   at org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:154)
   at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:87)
   at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:152)

When I try the Websphere specific TransactionManager for Spring, it's this configuration:

   <bean id="transactionManager"
      class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/>

   <!– process engine configuration –>
   <bean id="processEngineConfiguration"
      class="org.activiti.engine.impl.cfg.JtaProcessEngineConfiguration">
      <property name="dataSourceJndiName" value="jdbc/activitiDSH2" />
      <property name="transactionManager" ref="transactionManager" />
      <property name="transactionsExternallyManaged" value="true" />
      <property name="databaseSchemaUpdate" value="false" />
      
      <property name="mailServerHost" value="localhost" />
       <property name="mailServerPort" value="2525" /> 
       
   </bean>
And I get this output:
[06.06.11 13:12:20:699 CEST] 00000020 XmlBeanDefini I org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions Loading XML bean definitions from class path resource [activiti.cfg.xml]
[06.06.11 13:12:20:840 CEST] 00000020 ProcessEngine I   Activiti service  failed to initialize, see above.
[06.06.11 13:12:20:840 CEST] 00000020 RemoteExcepti E   CNTR0019E: EJB threw an unexpected (non-declared) exception during invocation of method "startProcessInstanceByKey". Exception data: com.ibm.ejs.container.CreateFailureException: ; nested exception is:
   org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'processEngineConfiguration' defined in class path resource [activiti.cfg.xml]: Initialization of bean failed; nested exception is org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'org.springframework.transaction.jta.WebSphereUowTransactionManager' to required type 'javax.transaction.TransactionManager' for property 'transactionManager'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [org.springframework.transaction.jta.WebSphereUowTransactionManager] to required type [javax.transaction.TransactionManager] for property 'transactionManager': no matching editors or conversion strategy found
   at com.ibm.ejs.container.StatelessBeanO.initialize(StatelessBeanO.java:404)

Caused by: java.lang.IllegalStateException: Cannot convert value of type [org.springframework.transaction.jta.WebSphereUowTransactionManager] to required type [javax.transaction.TransactionManager] for property 'transactionManager': no matching editors or conversion strategy found
   at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:289)
   at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:154)
   at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:452)
   … 69 more


What kind of configuration of the spring-beans would you suggest to re-use the transactions from websphere?


Thanks and Kind Regards,

Ingo
4 REPLIES 4

frederikherema1
Star Contributor
Star Contributor
I think you're problem lies with 'org.springframework.transaction.jta.WebSphereUowTransactionManager', which is actually as Spring-transaction-manager (org.spring….PlatformTransactionManager). When you want to use this one, you should use the SpringProcessEngineConfiguration.

The JTA process engine configuration needs a javax.transaction.TransactionManager…

ingo_ri
Champ in-the-making
Champ in-the-making
Your suggestion works fine, thanks.

johnnybravo
Champ in-the-making
Champ in-the-making
Hello,

if I understood correctly, you have successfuly managed to deploy Activiti to WebSphere 7.0.

I've been trying to do so in many different ways but there is always something missing.

I tried to do the same thing as you but in the final step when I set transactionManager class to javax.transaction.TransactionManager, it shows an error that TransactionManager cannot be instantiated because it is interface.


Could you please provide some more detailed info on what steps did you do to make it work?

Thank you

ingo_ri
Champ in-the-making
Champ in-the-making
Hi,

at the end of my investigation I had two different running configurations. The first is the spring-way. activiti-.cfg.xml looks like

<bean id="transactionManager"
  class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/>
 
<!– process engine configuration –>
<bean id="processEngineConfiguration"
  class="org.activiti.spring.SpringProcessEngineConfiguration">
  <property name="dataSourceJndiName" value="jdbc/activitiDSH2" />
  <property name="transactionManager" ref="transactionManager" />
  <property name="transactionsExternallyManaged" value="true" />
  <property name="databaseSchemaUpdate" value="false" />
 
  <property name="mailServerHost" value="localhost" />
  <property name="mailServerPort" value="2525" /> 
</bean>

The other one is the unofficial Websphere transaction manager way. activiti.cfg.xml looks like

<bean id="wsTransactionManager"
  class="de.ingo.spring.WebSphereJtaTransactionManager" >
  <property name="autodetectTransactionManager" value="false"/>
</bean>
<bean id="transactionManager"
  class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
  <property name="targetObject" ref="wsTransactionManager"/>
  <property name="targetMethod" value="getTransactionManager"/>
</bean>

<!– process engine configuration –>
<bean id="processEngineConfiguration"
  class="de.ingo.activiti.engine.impl.cfg.MySubclassFromProcessEngineConfiguration">
  <property name="dataSourceJndiName" value="jdbc/activitiDSH2" />
  <property name="transactionManager" ref="transactionManager" />
  <property name="transactionsExternallyManaged" value="true" />
  <property name="databaseSchemaUpdate" value="false" />
 
  <property name="mailServerHost" value="localhost" />
  <property name="mailServerPort" value="2525" />
</bean>

This class gets the transactionManager from Websphere.

package de.ingo.spring;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.transaction.TransactionManager;

import org.springframework.transaction.TransactionSystemException;
import org.springframework.transaction.jta.JtaTransactionManager;

public class WebSphereJtaTransactionManager extends JtaTransactionManager {

    private static final String FACTORY_CLASS_5_1 = "com.ibm.ws.Transaction.TransactionManagerFactory";
    private static final String FACTORY_CLASS_5_0 = "com.ibm.ejs.jts.jta.TransactionManagerFactory";
    private static final String FACTORY_CLASS_4 = "com.ibm.ejs.jts.jta.JTSXA";

private static final long serialVersionUID = 1L;

@Override
protected TransactionManager retrieveTransactionManager()
   throws TransactionSystemException {
  Class<?> clazz;
  try {
   logger.debug("Trying WebSphere 5.1+: " + FACTORY_CLASS_5_1);
   clazz = Class.forName(FACTORY_CLASS_5_1);
   logger.info("Found WebSphere 5.1+: " + FACTORY_CLASS_5_1);
  }
  catch (ClassNotFoundException ex) {
   logger.debug("Could not find WebSphere 5.1/6.0 TransactionManager factory class", ex);
   try {
    logger.debug("Trying WebSphere 5.0: " + FACTORY_CLASS_5_0);
    clazz = Class.forName(FACTORY_CLASS_5_0);
    logger.info("Found WebSphere 5.0: " + FACTORY_CLASS_5_0);
   }
   catch (ClassNotFoundException ex2) {
    logger.debug("Could not find WebSphere 5.0 TransactionManager factory class", ex2);
    try {
     logger.debug("Trying WebSphere 4: " + FACTORY_CLASS_4);
     clazz = Class.forName(FACTORY_CLASS_4);
     logger.info("Found WebSphere 4: " + FACTORY_CLASS_4);
    }
    catch (ClassNotFoundException ex3) {
     logger.debug("Could not find WebSphere 4 TransactionManager factory class", ex3);
     throw new TransactionSystemException(
       "Could not find any WebSphere TransactionManager factory class, " +
       "neither for WebSphere version 5.1+ nor 5.0 nor 4");
    }
   }
  }
 
  try {
   Method method = clazz.getMethod("getTransactionManager", (Class []) null);
   return (TransactionManager) method.invoke(null, (Object []) null);
  }
  catch (InvocationTargetException ex) {
   throw new TransactionSystemException(
     "WebSphere's TransactionManagerFactory.getTransactionManager method failed", ex.getTargetException());
  }
  catch (Exception ex) {
   throw new TransactionSystemException(
     "Could not access WebSphere's TransactionManagerFactory.getTransactionManager method", ex);
  }
}
}

Its not officially documented and recommended, but in our framework we do it the same way on WebSphere 7.