[JMS_SPEC-129] Resolve some undefined use cases when using Java EE transactions Created: 18/Jun/13  Updated: 22/Aug/13

Status: Open
Project: jms-spec
Component/s: None
Affects Version/s: 2.0
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: Nigel Deakin Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
is related to JMS_SPEC-130 Allow a JMSContext or Session to opt ... Open
is related to JMS_SPEC-131 Allow client-acknowledgement and loca... Open
Tags: jms21-forreview-major

 Description   

Case 1

The JMS 2.0 specification, section 12.3 "Behaviour of JMS sessions in the Java EE web or EJB container" states that if a Session or JMSContext is created when there is an active JTA transaction in progress then the Session or JMSContext will participate in the JTA transaction and will be committed or rolled back when the JTA transaction is committed or rolled back.

However the specification also states that "if a Session or JMSContext is created when there is an active JTA transaction but is subsequently used to send or receive messages when there is no active JTA transaction then the behaviour is undefined".

Issue 1: Can we define what should happen if a Session or JMSContext is created in a JTA transaction but is used to send or receive a message after the JTA transaction has been committed or rolled back?

Here's a simple example:

@Stateless
@LocalBean
@TransactionManagement(value=TransactionManagementType.BEAN)
public class MySessionBean {
       
   @Resource(lookup="jms/myConnectionFactory") ConnectionFactory connectionFactory;
   @Resource(lookup="jms/myQueue") Queue queue;
   
   @Inject UserTransaction ut;
      
   public void doSomething() {
   
      // start a transaction   
      ut.begin();

      // create JMSContext when there is a transaction                      
      JMSContext context = connectionFactory.createContext();

      // commit the transaction
      ut.commit();
      
      // what happens here?            
      context.createProducer().send(queue,"Hello world");
 
      context.close();
   }
}

There appear to be three possibilities:

  • This is a programming error and the use of the JMSContext (or Session) outside of the transaction should throw an exception
  • Any messages sent or received outside of the transaction will be non-transacted and automatically-acknowledged
  • The behaviour must remain undefined

Does it matter if the transaction was rolled back in another thread? (if this is a possible use case).

What happens if we then start a second transaction and use the same JMSContext to send or receive a message (as in the example below)?

@Stateless
@LocalBean
@TransactionManagement(value=TransactionManagementType.BEAN)
public class MySessionBean {
       
   @Resource(lookup="jms/myConnectionFactory") ConnectionFactory connectionFactory;
   @Resource(lookup="jms/myQueue") Queue queue;
   
   @Inject UserTransaction ut;
      
   public void doSomething() {
   
      // start a transaction   
      ut.begin();

      // create JMSContext when there is a transaction                      
      JMSContext context = connectionFactory.createContext();

      // commit the transaction
      ut.commit();
      
      context.createProducer().send(queue,"Hello world");

      // start a second transaction   
      ut.begin();

      // is this valid?          
      context.createProducer().send(queue,"Hello world");

      // commit the transaction
      ut.commit();
 
      context.close();
   }
}

Case 2

Conversely, the JMS 2.0 specification states that if a Session or JMSContext is created when there is no active JTA transaction in progress, then the Session or JMSContext that is created will be non-transacted and any messages received will be automatically acknowledged.

However the specification also states that "if a Session or JMSContext is created when there is no active JTA transaction but subsequently used to send or receive messages when there is an active JTA transaction then the behaviour is undefined."

Issue 2: Can we define what should happen if a Session or JMSContext is created when there is no JTA transaction but is used to send or receive a message when there is an active JTA transaction?

Here's a simple example:

@Stateless
@LocalBean
@TransactionManagement(value=TransactionManagementType.BEAN)
public class MySessionBean {
       
   @Resource(lookup="jms/myConnectionFactory") ConnectionFactory connectionFactory;
   @Resource(lookup="jms/myQueue") Queue queue;
   
   @Inject UserTransaction ut;
      
   public void doSomething() {

      // create JMSContext when there is no transaction                      
      JMSContext context = connectionFactory.createContext();

      // now start a transaction
      ut.begin();
      
      // is this message part of the transaction or not?             
      context.createProducer().send(queue,"Hello world");

      // now commit the transaction
      ut.commit();

      context.close();
   }
}

There appear to be four possibilities:

  • This is a programming error and the use of the JMSContext (or Session) outside of the transaction should throw an exception
  • Any messages sent or received whilst there is a JTA transaction must participate in the transaction
  • Any messages sent or received whilst there is a JTA transaction must not participate in the transaction.
  • This must remain undefined


 Comments   
Comment by John D. Ament [ 18/Jun/13 ]

Equivalently, what happens in EJB when this occurs?

Comment by Nigel Deakin [ 18/Jun/13 ]

John, can you please clarify your question? This issue affects any Java EE component that the UserTransaction API.

N.B. I'm going to log some more issues shortly on related issues.

Comment by Nigel Deakin [ 18/Jun/13 ]

Added some code examples to the initial issue description

Comment by Nigel Deakin [ 18/Jun/13 ]

Updated summary field.

Comment by Nigel Deakin [ 22/Aug/13 ]

The same issues arise for container-managed transactions.

Issue 1 also arises for container-managed transactions as follows: Imagine a stateful session bean with two business methods. The first method has a transactional attribute REQUIRED. This creates a JMSContext or Session and saves it in a field. The second method has a transactional attribute NOT_SUPPORTED. This method uses that JMSContext or Session to send a message. A client calls the first method and then the second.

Issue 2 also arises for container-managed transactions as follows: Imagine a stateful session bean with two business methods. The first method has a transactional attribute NOT_SUPPORTED. This creates a JMSContext or Session and saves it in a field. The second method has a transactional attribute REQUIRED. This method uses that JMSContext or Session to send a message. A client calls the first method and then the second.

Generated at Thu Sep 03 01:09:47 UTC 2015 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.