Spring and Weblogic Integration XA problem
I am have got a nasty problem with XA transactions and the WebLogic Integration.
I have got things configured as follows:
EJB handling JTA transactions.
DAO interface.
DAO implementation class.
Spring SQL operations for CRUD.`
I can get XA transactions working okay in a Weblogic J2EE container but as soon as I deploy them into WLI and they are called by a process I get trouble.
This is running on
Weblogic 8.1 sp4
Oracle Type IV driver bundled in Weblogic
Oracle 9.2.0.4
Windows/Solaris
The system is as follows we have a WLI process subscribing to a topic this calls a stateless session bean to persist data.
We have a WLI process that is kicked off by subscribing to a topic. The process puts the xml it receives into the database.
The process fails in after a being called a several times with the following error.
Workshop Log
==========
09 May 2005 10:40:14,637 WARN AsyncErrorBean [ExecuteThread: '11' for queue: 'weblogic.kernel.Default'][]: A message was unable to be delivered from a WLW Message Queue. Attempting to deliver the onAsyncFailure event
WLI Console process drill down screen
=============================
Service URI /Processes/uk/foobar/bsa/bartime/processes/M0GenericPD.jpd
Instance ID 10.0.0.25-993445.103c102d280.-7fcb
Exception Stack Trace java.lang.Throwable: Process aborted due to transaction rollback
at com.bea.wli.bpm.runtime.JpdContainer$TxnListener.a bortProcess(JpdContainer.java:510)
at com.bea.wli.bpm.runtime.JpdContainer$TxnListener.a fterCompletion(JpdContainer.java:444)
at weblogic.transaction.internal.ServerSCInfo.callAft erCompletions(ServerSCInfo.java:853)
at weblogic.transaction.internal.ServerTransactionImp l.callAfterCompletions(ServerTransactionImpl.java: 2789)
at weblogic.transaction.internal.ServerTransactionImp l.setRolledBack(ServerTransactionImpl.java:2636)
at weblogic.transaction.internal.ServerTransactionImp l.globalRetryRollback(ServerTransactionImpl.java:2 866)
at weblogic.transaction.internal.ServerTransactionImp l.globalRollback(ServerTransactionImpl.java:2626)
at weblogic.transaction.internal.ServerTransactionImp l.internalCommit(ServerTransactionImpl.java:323)
at weblogic.transaction.internal.ServerTransactionImp l.commit(ServerTransactionImpl.java:246)
at weblogic.ejb20.internal.MDListener.execute(MDListe ner.java:400)
at weblogic.ejb20.internal.MDListener.onMessage(MDLis tener.java:262)
at weblogic.jms.client.JMSSession.onMessage(JMSSessio n.java:2678)
at weblogic.jms.client.JMSSession.execute(JMSSession. java:2598)
at weblogic.kernel.ExecuteThread.execute(ExecuteThrea d.java:219)
at weblogic.kernel.ExecuteThread.run(ExecuteThread.ja va:178)
WebLogic Server Log shows:
======================
<09-May-2005 10:40:14 o'clock GMT> <Warning> <WLW> <000000> <A message was unable to be delivered from a WLW Message Queue. Attempting to deliver the onAsyncFailure event>
<09-May-2005 10:40:14 o'clock GMT> <Error> <EJB> <BEA-010026> <Exception occurred during commit of transaction Xid=BEA1-02140A1C28AAB16BE9F2(340479),Status=Rolled back.
[Reason=oracle.jdbc.xa.OracleXAException],numRepliesOwedMe=0,numRepliesOwe
edback),properties=({}),local properties=({}),OwnerTransactionManager=ServerTM[ServerCoordinatorDescriptor=(CoordinatorURL=cgServ er+10.0.0.25:7001+platform+t3+,
XAResources={},NonXAResources={})],CoordinatorURL=cgServer+10.0.0.25:7001+platform
at oracle.jdbc.xa.OracleXAResource.checkError(OracleX AResource.java:1017)
at oracle.jdbc.xa.client.OracleXAResource.start(Oracl eXAResource.java:227)
at oracle.jdbc.xa.OracleXAResource.resumeStacked(Orac leXAResource.java:341)
at oracle.jdbc.xa.client.OracleXAResource.prepare(Ora cleXAResource.java:545)
at weblogic.jdbc.wrapper.VendorXAResource.prepare(Ven dorXAResource.java:70)
at weblogic.jdbc.jta.DataSource.prepare(DataSource.ja va:890)
at weblogic.transaction.internal.XAServerResourceInfo .prepare(XAServerResourceInfo.java:1234)
at weblogic.transaction.internal.XAServerResourceInfo .prepare(XAServerResourceInfo.java:441)
at weblogic.transaction.internal.ServerSCInfo$1.execu te(ServerSCInfo.java:253)
at weblogic.kernel.ExecuteThread.execute(ExecuteThrea d.java:219)
at weblogic.kernel.ExecuteThread.run(ExecuteThread.ja va:178)
--------------- nested within: ------------------
weblogic.transaction.RollbackException: Could not prepare resource 'CCIBSAConnectionPool - with nested exception:
[oracle.jdbc.xa.OracleXAException]
at weblogic.transaction.internal.TransactionImpl.thro wRollbackException(TransactionImpl.java:1683)
at weblogic.transaction.internal.ServerTransactionImp l.internalCommit(ServerTransactionImpl.java:325)
at weblogic.transaction.internal.ServerTransactionImp l.commit(ServerTransactionImpl.java:246)
at weblogic.ejb20.internal.MDListener.execute(MDListe ner.java:400)
at weblogic.ejb20.internal.MDListener.onMessage(MDLis tener.java:262)
at weblogic.jms.client.JMSSession.onMessage(JMSSessio n.java:2678)
at weblogic.jms.client.JMSSession.execute(JMSSession. java:2598)
at weblogic.kernel.ExecuteThread.execute(ExecuteThrea d.java:219)
at weblogic.kernel.ExecuteThread.run(ExecuteThread.ja va:178)
.>
This causes an in doubt transaction in the oracle dba_2pc_pending table after which everything is blocked until the Weblogic Server is rebooted and the in doubt transaction is cleared.
I have the following context:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!--
THIS IS PRODUCED BY CODE GENERATION DO NOT HAND EDIT.
Code generator template properties.
CHECK IN YOUR GENERATED CODE WITHOUT KEYWORD SUBSTITUTION IF YOU
WANT THIS TO REMAIN MEANINGFUL.
$Source: C:/cvs/BSA-CODEGEN/plugins/spring12Dao/src/middlegen/plugins/spring12dao/spring12-weblogic-application-context.vm,v $
$Log: spring12-weblogic-application-context.vm,v $
Revision 1.1 2005/04/29 13:47:22 john
no message
-->
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryB ean">
<property name="jndiName">
<value>jdbc.foo.bar</value>
</property>
</bean>
<bean id="FndLookupTypeInsert" class="com.foobar.FndLookupTypeInsert">
<constructor-arg><ref bean="dataSource"/></constructor-arg>
</bean>
<bean id="FndLookupValue" class="com.foobar.FndLookupValueDAOImpl">
<property name="insertOperation"><ref local="FndLookupValueInsert"/></property>
</bean>
</beans>
My EJB looks like this:
package com.foobar;
/*
* $Source: C:/cvs/BSA-CODEGEN/plugins/ejbSpring12Dao/src/middlegen/plugins/ejbspring12dao/ejb-spring12-dao.vm,v $
*
* $Log: ejb-spring12-dao.vm,v $
* Revision 1.4 2005/05/04 08:36:42 john
* added minimum in pool
*
* Revision 1.3 2005/04/14 10:04:06 john
* inc changes
*
* Revision 1.2 2005/04/08 08:19:22 john
* changed interfaces to work in cluster
*
* Revision 1.1 2005/04/07 16:32:46 john
* moved added version number
*
*/
import weblogic.transaction.TransactionHelper;
import javax.ejb.CreateException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.io.Serializable;
import java.util.List;
import java.util.Date;
/**
* <p/>
* EJB DAO implementation for FndLookupType. The EJB class provides
* transactions, security and failover. The EJB delegates to DAO implementation which
* is configured by Spring. The implementation is responsible for all database interaction.
* <p/>
* Note that to operate without compromising data integrity in a clustered environment and
* to support failover all methods must be idempotent. This means they can be replayed
* without ill effect. This is clear not the case for data access EJBs hence a transactional
* token has been added to ensure that if a replay occurs is second invocation by the container
* will not result in any changes in the database if they have already occurred before.
*
*
* THIS IS PRODUCED BY CODE GENERATION DO NOT HAND EDIT.
*
* @author BSA Code Generator Version: 0.11
* @version $Revision: 1.4 $
*
* @ejbgen:session ejb-name = "FndLookupTypeDAO" enable-call-by-reference = "true" initial-beans-in-free-pool="1"
*
* @ejbgen:jndi-name remote = "ejb.foobar.FndLookupTypeDAORemoteHome"
*
* @ejbgen:file-generation
* remote-class = "true"
* remote-class-name = "FndLookupTypeDAOEJBRemote"
* remote-home = "true"
* remote-home-name = "FndLookupTypeDAOEJBHome"
*
* @ejbgen:env-entry name="ejb/BeanFactoryPath" type="java.lang.String" value="applicationContext.xml"
*/
public class FndLookupTypeDAOEJB extends AbstractStatelessSessionBean
{
/** logger **/
private static final LWLogger logger = LoggerFactory.getLWLogger(FndLookupTypeDAOEJB.clas s.getName());
/** DAO implementation class */
FndLookupTypeDAO dao;
/** The data source */
private DataSource dataSource;
/**
* Set up reference to dao implementation.
*/
protected void onEjbCreate() throws CreateException {
dao = (FndLookupTypeDAO) getBeanFactory().getBean("FndLookupType");
try {
InitialContext ic = new InitialContext();
dataSource = (DataSource) ic.lookup("ds.core.cci.bsa.xa");
} catch (NamingException e) {
logger.error(e);
throw new CreateException();
}
}
/**
* Insert the object into the database.
*
* @param obj The object to save.
* @param a transactional token
*
* @return The primary key of the newly inserted object.
*
* @ejbgen:remote-method is-idempotent="true" transaction-attribute="Required"
*
*/
public void insert( FndLookupType obj, long transactionalToken ) {
if (logger.isDebugEnabled()) {
logger.debug(">> insert " + obj + "transaction token " + transactionalToken);
TransactionHelper th = TransactionHelper.getTransactionHelper();
logger.debug("Transaction id " + th.getTransaction() );
}
// if we are not in a replay then do an insert
if(!TransactionalTokenLoggingService.query(dataSou rce,transactionalToken)) {
dao.insert( obj );
TransactionalTokenLoggingService.insert(dataSource ,transactionalToken);
}
}
/**
* Update the object in the database.
*
* @param obj The object to update.
* @param a transactional token
*
* @ejbgen:remote-method is-idempotent="true" transaction-attribute="Required"
*
*/
public void update( FndLookupType obj , long transactionalToken) {
if (logger.isDebugEnabled()) {
logger.debug(">> update " + obj + "transaction token " + transactionalToken);
TransactionHelper th = TransactionHelper.getTransactionHelper();
logger.debug("Transaction id " + th.getTransaction() );
}
// if we are not in a replay then do an insert
if(!TransactionalTokenLoggingService.query(dataSou rce,transactionalToken)) {
dao.update( obj );
TransactionalTokenLoggingService.insert(dataSource ,transactionalToken);
}
}
/**
* Delete the object in the database.
*
* @param obj The object to update.
* @param a transactional token
*
* @ejbgen:remote-method is-idempotent="true" transaction-attribute="Required"
*
*/
public void delete( FndLookupType obj, long transactionalToken ) {
if (logger.isDebugEnabled()) {
logger.debug(">> delete " + obj + "transaction token " + transactionalToken);
TransactionHelper th = TransactionHelper.getTransactionHelper();
logger.debug("Transaction id " + th.getTransaction() );
}
// if we are not in a replay then do an insert
if(!TransactionalTokenLoggingService.query(dataSou rce,transactionalToken)) {
dao.delete( obj );
TransactionalTokenLoggingService.insert(dataSource ,transactionalToken);
}
}
/**
* Retrieve all objects of this type from the database.
*
* @return All objects of this type from the database.
*
* @ejbgen:remote-method is-idempotent="true" transaction-attribute="Required"
*
*/
public List findAll() {
if (logger.isDebugEnabled()) {
logger.debug(">> findall ");
TransactionHelper th = TransactionHelper.getTransactionHelper();
logger.debug("Transaction id " + th.getTransaction() );
}
return dao.findAll();
}
/**
* Find object by primary key
*
* @param pk the pk of the object to find.
*
* @ejbgen:remote-method is-idempotent="true" transaction-attribute="Required"
*
*/
public FndLookupType findByPK( Serializable pk ) {
if (logger.isDebugEnabled()) {
logger.debug(">> findByPK ");
TransactionHelper th = TransactionHelper.getTransactionHelper();
logger.debug("Transaction id " + th.getTransaction() );
}
return dao.findByPK( pk );
}
// No $plugin.mergedir/ejbspring12dao-fnd_lookup_types-class-code.txt found.
}
My DAO implementation looks like this:
package com.foobar;
/*
* Code generator template properties.
*
* CHECK IN YOUR GENERATED CODE WITHOUT KEYWORD SUBSTITUTION IF YOU
* WANT THIS TO REMAIN MEANINGFUL.
*
* $Source: C:/cvs/BSA-CODEGEN/plugins/spring12Dao/src/middlegen/plugins/spring12dao/spring-dao-impl.vm,v $
*
* $Log: spring-dao-impl.vm,v $
* Revision 1.1 2005/04/29 13:47:22 john
* no message
*
*
*/
import org.springframework.dao.DataAccessException;
import java.io.Serializable;
import java.util.List;
import java.util.Date;
/**
* <p/>
* Spring 1.2 based DAO Implementation using Spring Framework classes for database
* operations for FndLookupType.
* <p/>
* Please see SpringFramework reference manual overview of IOC for details of how this object
* and its sub components are wired up.
* <p/>
* For out of container testing this uses JDBC transactions.
* <p/>
* For in container usage the transactions are delegated to Weblogic.
*
* THIS IS PRODUCED BY CODE GENERATION DO NOT HAND EDIT.
*
* @see org.springframework.jdbc
* @see org.springframework.jdbc.object
*
* No $plugin.mergedir/spring12dao-dao-ALL-class-comments.txt found.
* No $plugin.mergedir/spring12dao-dao-fnd_lookup_types-class-comments.txt found.
*
* @author BSA Code Generator Version: 0.11
*
*/
public class FndLookupTypeDAOImpl implements FndLookupTypeDAO {
/** logger. */
private LWLogger logger = LoggerFactory.getLWLogger(FndLookupTypeDAOImpl.cla ss.getName());
/** insert operation */
private FndLookupTypeInsert insertOperation;
/**
* Insert the object into the database.
*
* @param obj The object to save.
*/
public void insert( FndLookupType obj ) throws org.springframework.dao.DataAccessException {
if (logger.isDebugEnabled()) {
logger.debug("Inserting " + obj);
}
try {
insertOperation.executeInsert(obj);
} catch (org.springframework.dao.DataAccessException e) {
logger.error(e);
throw e;
}
}
/**
* Update the object in the database.
*
* @param obj The object to update.
*/
public void update( FndLookupType obj ) throws org.springframework.dao.DataAccessException {
// not implemented
throw new UnsupportedOperationException();
}
/**
* Delete the object in the database.
*
* @param obj The object to update.
*/
public void delete( FndLookupType obj ) throws org.springframework.dao.DataAccessException {
// not implemented
throw new UnsupportedOperationException();
}
/**
* Retrieve all objects of this type from the database.
*
* @return All objects of this type from the database.
*/
public List findAll() throws org.springframework.dao.DataAccessException {
// not implemented
throw new UnsupportedOperationException();
}
/**
* Find object by primary key.
* @param pk the pk of the object to find.
*/
public FndLookupType findByPK( Serializable pk ) throws org.springframework.dao.DataAccessException {
// not implemented
throw new UnsupportedOperationException();
}
/** Accessor for insert class*/
public void setInsertOperation(final FndLookupTypeInsert pInsertOperation) {
insertOperation = pInsertOperation;
}
/** Accessor for insert class*/
public FndLookupTypeInsert getInsertOperation() {
return insertOperation;
}
}
And my database operation looks like this:
package com.foobar;
/*
* Code generator template properties.
*
* CHECK IN YOUR GENERATED CODE WITHOUT KEYWORD SUBSTITUTION IF YOU
* WANT THIS TO REMAIN MEANINGFUL.
*
* $Source: C:/cvs/BSA-CODEGEN/plugins/spring12Dao/src/middlegen/plugins/spring12dao/spring-insert.vm,v $
*
* $Log: spring-insert.vm,v $
* Revision 1.1 2005/04/29 13:47:22 john
* no message
*
*
*/
import java.sql.Types;
import javax.sql.DataSource;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.object.SqlUpdate;
/**
* <p/>
* Spring database operation to insert an object of type FndLookupType
* into the database table FND_LOOKUP_TYPES.
* <p/>
* Please see SpringFramework reference manual overview of IOC for details of how this object
* and its sub components are wired up.
* <p/>
* For out of container testing this uses JDBC transactions.
* <p/>
* For in container usage the transactions are delegated to Weblogic.
*
* THIS IS PRODUCED BY CODE GENERATION DO NOT HAND EDIT.
*
* @see org.springframework.jdbc
* @see org.springframework.jdbc.object
*
* No $plugin.mergedir/spring12dao-dao-ALL-class-comments.txt found.
* No $plugin.mergedir/spring12dao-dao-fnd_lookup_types-class-comments.txt found.
*
* @author BSA Code Generator Version: 0.11
*/
public class FndLookupTypeInsert extends SqlUpdate {
/** logger. */
private LWLogger logger = LoggerFactory.getLWLogger(FndLookupTypeInsert.clas s.getName());
/** the sql clause used to insert the record */
public String INSERT_CLAUSE = "INSERT INTO FND_LOOKUP_TYPES (APPLICATION_ID,LOOKUP_TYPE,CUSTOMIZATION_LEVEL,CR EATION_DATE,LAST_UPDATE_DATE,ZOOP_ACTION_TYPE,ZOOP _ACTION_DATE_TIME) VALUES (?,?,?,?,?,?,?)";
/**
* Default Constructor.
*
* @param dataSource the datasource to use
*/
public FndLookupTypeInsert(final DataSource dataSource) {
setSql(INSERT_CLAUSE );
setDataSource(dataSource);
declareParameter(new SqlParameter(Types.NUMERIC));
declareParameter(new SqlParameter(Types.VARCHAR));
declareParameter(new SqlParameter(Types.VARCHAR));
declareParameter(new SqlParameter(Types.DATE));
declareParameter(new SqlParameter(Types.DATE));
declareParameter(new SqlParameter(Types.VARCHAR));
declareParameter(new SqlParameter(Types.DATE));
compile();
}
/**
* Perform the insert.
*
* @param obj the object to insert.
*/
public void executeInsert(final FndLookupType obj) {
Object[] params = new Object[] { new java.lang.Long(obj.getApplicationId()),obj.getLook upType(),obj.getCustomizationLevel(),obj.getCreati onDate(),obj.getLastUpdateDate(),obj.getActionType (),obj.getActionDateTime() };
update(params);
}
}
Any help with the following would be fantastic:
Does the above look okay for what I am trying to achieve (XA DAO persistance layer)?
Has anyone had any problems with Weblogic, Weblogic intergration and Spring which gave similar stack trace - or know why I don't get the true XA error code.
I know this isn't a wl forum but any information on Transactions in WLI would be great - I don't think WLI process runtime is as simple as a MDB Bean calling my DAOin one transcation.
Any other pointers?
Many Thanks,
JohnD