jakartaee / jakartaee/messaging

Resolve some undefined use cases when using Java EE transactions

Open
#129 9 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

jms21-forreview-major Priority: Major Type: Improvement
Dominant language
Java
Stars
49
Forks
34
PR merge metrics
No merged PRs in 30d

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
#### Affected Versions
[2.0]

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing JMS 2.0 specification section 12.3 and the two transaction examples in this issue. Resolve the undefined behavior for sessions and JMSContext instances used before or after JTA transactions, including reuse across a second transaction and rollback in another thread. Done means an agreed specification decision covering both cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend-api-design
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.