container-managed transacation; problem with rollback

Hi,

i'd like to be advised in following problem:

I am using Session bean with container-managed transacation to publish message to topic trougth JMS.

Transaction's attribute is Required.

Topic is created in ORACLE DB using ORACLE Advanced Queueing technology. Session bean is deployed to OC4J container.

My problem is following scenario:

- message is published : topicPublisher.publish(topic ,message);

- topic connection is closed: topicConnection.close();

- exception is thrown after enqueue method has been finished in the other method that is in the same transaction as enqueue method

- transaction is marked as Rollbacked (is done by container)

- message gets to (is enqueued into) and remains in topic even though transaction has been marked as rollbacked

Source code:

...

private SessionContext context = null;

...

public void enqueue(String msg){

TopicConnectionFactory topicCF = null;

Topic topic = null;

TopicConnection topicConnection = null;

TopicSession topicSession = null;

TopicPublisher topicPublisher = null;

Message message = null;

try {

if (jndiContext == null){

jndiContext = new InitialContext();

}

//topic connection factory

topicCF = (TopicConnectionFactory)jndiContext.lookup (java:comp/resource/aq_test/TopicConnectionFactories/QUEUE_NAME);

// topic

topic = (Topic)jndiContext.lookup(java:comp/resource/aq_test/Topics/QUEUE_NAME);

topicConnection = topicCF.createTopicConnection();

topicConnection.start();

// according advice in JMS 1.1 tuttorial

topicSession = topicConnection.createTopicSession( treu, 0);

topicPublisher = topicSession.createPublisher(topic);

message = topicSession.createTextMessage(msg);

topicPublisher.publish(topic ,msg);

} catch(NamingException ex) {

System.err.println("topic or factory for topic's connection wasn't found in IniatialContext");

ex.printStackTrace();

context.setRollbackOnly();

} catch (JMSException ex) {

System.err.println("error while enqueueing topic");

ex.printStackTrace();

context.setRollbackOnly();

} finally {

try {

// Closing resources

topicPublisher.close();

topicSession.close();

topicConnection.close();

} catch (JMSException ex) {

System.out.println("error by enqueueing topic while closing topic errors");

ex.printStackTrace();

context.setRollbackOnly();

}

}

}

Thank you very much for any suggestions and hints.

lubbis

[2688 byte] By [lubbis2002] at [2007-9-30 22:06:07]
# 1
Hi, lubbis,When you call method enqueue from a non-transacted client, returning from enqueue will cause container to commit the transaction.--Dianne
djiao at 2007-7-7 11:19:13 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 2
hi,enqueue method and method that is called after enqueue method, which causes the exception, are business method of the same Session EJB. This methods are executed in the same transaction (i hope). Session EJB is of container-managed transaction type.lubbis
lubbis2002 at 2007-7-7 11:19:13 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 3

Hi, lubbis,

Actually, it is determined by if client is transacted or not:

client -> enqueue

client -> other methods

If client is not transacted, then when enqueue returns, container will try to commit the transaction.

This is documented in EJB spec "17.6.2.2 Required":

"The container must invoke an enterprise bean method whose transaction attribute is set to Required with a valid transaction context.

If a client invokes the enterprise bean s method while the client is associated with a transaction context, the container invokes the enterprise bean s method in the client s transaction context.

If the client invokes the enterprise bean s method while the client is not associated with a transaction context, the container automatically starts a new transaction before delegating a method call to the enterprise bean business method. The container automatically enlists all the resource managers accessed by the business method with the transaction. If the business method invokes other enterprise beans, the container passes the transaction context with the invocation. The container attempts to commit the transaction when the business method has completed. The container performs the commit protocol before the method result is sent to the client."

--Dianne

djiao at 2007-7-7 11:19:13 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 4

Hi,

thank you vey much for your hints.

All methods are called from single business Session EJB method, that's transaction type is Required.

According EJB specification, if client is in transaction then Session EJB joins the trsanaction and if client isn't in trsansaction, new transaction is created for invokod method. In both cases, all methods are expected to be in the same transaction. They are but by rollbacking the current transaction, enqueued message isn't rollbacked.

I got a feeling, problem is with JMS provider and it's implementaion of JMS. Because transaction doesn't behave like it is expected to behave.

lubbis

lubbis2002 at 2007-7-7 11:19:13 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 5
Hi, Lubbis,Did you verify it is not rollbacked? Could you receive the message in the queue?--Dianne
djiao at 2007-7-7 11:19:13 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 6
Hi,i verified that the transaction had been roolbacked, but the message was stored in queue. I was able to dequeue that message using message-driven bean.Lubbis
lubbis2002 at 2007-7-7 11:19:13 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 7

Hi,

problem was caused by using the wrong type of data source.

OrionCMTDataSource has to used instead of DriverManagerDataSource.

There are 2 approaches, how to solve this problem:

1.

Using DriverManagerDataSource but specifying a "ejb-location" attribute. Orion will bind a OrionCMTDataSource to the specified location. In order to instantiate the OrionCMTDataSource at the specified location, a xa-location attribute needs to be given with a bound DriverManagerXADataSource.

By trying to connect to AQ Topic or to database, connection should be retrieved from data source using "ejb-location" attribute.

For more information see:

http://www.orionserver.com/docs/datasource-configuration.html#emulating-cmt

2.

Using Non-emulated (OrionCMTDataSource) instead of Emulated Data Source (DriverManagerDataSource ).

For more information see:

http://download-west.oracle.com/docs/cd/B10464_01/web.904/b10326/datasrcs.htm#10

lubbis

lubbis2002 at 2007-7-7 11:19:13 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...