Injection of JMSContext objects - Use Cases F - K (version 4)
This page relates to JSR 343 (JMS 2.0) which has been released. It is retained here as a historical record and in case it proves useful to a future JMS expert group.
This page contains a number of use cases which demonstrate how the scope proposed in Injection of JMSContext objects - Proposals (version 4) would appear to users. Each use case is followed by an analysis.
Before reading these, read Injection of JMSContext objects - Use Cases A-E (version 4).
Note that these examples do not use the proposed new JMSContext
API for sending messages described in Proposed changes to JMSContext to support injection (Option 4).
- Use case F: One bean which calls another when there is no transaction
- Use case G: One bean method which uses two transactions
- Use case H. A bean which uses a context both outside and within a transaction
- Use case J. Two separate container-managed transactions on the same thread, one suspended before the second is started
- Use case K. One bean which calls another within the same transaction, but using different connection factories
Use case F: One bean which calls another when there is no transaction
Consider two stateless session beans, Bean1
and Bean2
.
Bean1
is configured to use bean-managed transactions and has a business method method1
. The bean has an injected JMSContext
. method1
does not start a transaction, uses this context to send a message, and then invoke method2
on Bean2
.
Bean2
is also configured to use bean-managed transactions and has a business method method2
. The bean has an injected JMSContext
. method2
does not start a transaction and simply uses this context to send a second message.
A remote client obtains a reference to Bean1
and calls method1
.
This is Bean1
@TransactionManagement(TransactionManagementType.BEAN)
@Stateless
public class Bean1 {
@Resource(lookup="jms/inboundQueue") Queue queue;
@Inject
@JMSConnectionFactory("jms/connectionFactory")
JMSContext context;
@EJB Bean2 bean2;
public void method1() {
context.send(queue,"Message 1");
bean2.method2();
}
}
This is Bean2
@TransactionManagement(TransactionManagementType.BEAN)
@Stateless
public class Bean2 {
@Resource(lookup="jms/inboundQueue") Queue queue;
@Inject
@JMSConnectionFactory("jms/connectionFactory")
JMSContext context;
public void method2() {
context.send(queue,"Message 2");
}
}
Case F: Analysis
Q | A |
---|---|
Are the context variables in the two calls to context.send() injected using identical annotations? |
Yes. Although they use separate variable declarations, both declarations use identical annotations. |
What scope do the context variables in the two calls to context.send() have? |
Both calls to context.send() take place when there is no transaction, so they both have request scope. |
Are the context variables in the two calls to context.send() in the same scope? |
Yes, since the two calls to context.send() take place in the same request |
Do the context variables in the two calls to context.send() use the same JMSContext (and therefore MessageProducer ) objects? |
Yes. They are injected using identical annotations and have the same request scope. |
Are the two messages guaranteed to be delivered in the order in which they are sent? | Yes, since they are sent using the same MessageProducer object. |
Case F: JMSContext lifecycle
The JMSContext
object will be created when method1
uses context
for the first time, and destroyed when method1 returns.
The same behaviour should apply when the bean is configured to use container-managed transactions but the transaction attribute type is NEVER
or NOT_SUPPORTED
.
Use case G: One bean method which uses two transactions
Consider a stateless session bean Bean1
. This is configured to use bean-managed transactions and has one business method, method1
. The bean has an injected JMSContext
. method1
starts a transaction and uses the context to send two messages. It then commits the transaction and starts a second transaction. It then uses the context to send two further messages and finally commits the second transaction.
A remote client obtains a reference to Bean1
and calls method1
.
@TransactionManagement(TransactionManagementType.BEAN)
@Stateless
public class Bean1 {
@Resource(lookup="jms/inboundQueue") Queue queue;
@Inject
@JMSConnectionFactory("jms/connectionFactory")
JMSContext context;
@Inject UserTransaction ut;
public void method1() {
ut.begin();
context.send(queue,"Message 1");
context.send(queue,"Message 2");
ut.commit();
ut.begin();
context.send(queue,"Message 3");
context.send(queue,"Message 4");
ut.commit();
}
}
Case G: Analysis
Q | A |
---|---|
Are the context variables in the four calls to context.send() injected using identical annotations? |
Yes, since they use the same variable declaration. |
What scope do the context variables in the four calls to context.send() have? |
All four calls to context.send() take place within a transaction, so the context variables all have transaction scope. |
Are the context variables in the four calls to context.send() in the same scope? |
The first and second calls to context.send() take place in one transaction and the third and fourth calls to context.send() take place in another transaction. This means the context variables in the first and second calls are in one transaction scope, and the context variables in the third and fourth calls are in a different transaction scope. |
Do the context variables in the four calls to context.send() use the same JMSContext (and therefore MessageProducer ) objects? |
All four context variables are injected using identical annotatons. The context variables in the first and second calls are in the same transaction scope and so share the same JMSContext (and therefore MessageProducer ) object. The context variables in the third and fourth calls are in a different transaction scope and so share a different JMSContext (and therefore MessageProducer ) object. |
Are the four messages guaranteed to be delivered in the order in which they are sent? | The first and second messages share one MessageProducer object and are delivered in order, and the third and fourth messages share a different MessageProducer object and are delivered in order. However there is no guarantee that the first and second messages will be delivered before the third and fourth messages. |
Case G: JMSContext lifecycle
The JMSContext
object used by the first and second calls to context.send()
will be created when the first call to context.send()
takes place, and will be destroyed when the first transaction is committed.
The JMSContext
object used by the third and fourth calls to context.send()
will be created when the third call to context.send()
takes place, and will be destroyed when the second transaction is committed.
Use case H. A bean which uses a context both outside and within a transaction
Consider a stateless session bean Bean1
. This is configured to use bean-managed transactions and has one business method, method1
. The bean has an injected JMSContext
. method1
does not start a transaction and uses the context
variable to send two messages. It then starts a transaction and uses the context
variable to send a third message. It then commits the transaction and uses the context
variable to send a fourth and fifth more messages.
A remote client obtains a reference to Bean1
and calls method1
.
@TransactionManagement(TransactionManagementType.BEAN)
@Stateless
public class Bean1 {
@Resource(lookup="jms/inboundQueue") Queue queue;
@Inject
@JMSConnectionFactory("jms/connectionFactory")
JMSContext context;
@Inject UserTransaction ut;
public void method1() {
context.send(queue,"Message 1");
context.send(queue,"Message 2");
ut.begin();
context.send(queue,"Message 3");
ut.commit();
context.send(queue,"Message 4");
context.send(queue,"Message 5");
}
}
Case H: Analysis
Q | A |
---|---|
Are the context variables in the five calls to context.send() injected using identical annotations? |
Yes, since they use the same variable declaration. |
What scope do the context variables in the five calls to context.send() have? |
The first, second, fourth and fifth calls to context.send() take place without a transaction, so these context variables have request scope. The third call to context.send() take place within a transaction, and so this context variable has transaction scope. |
Are the context variables in the five calls to context.send() in the same scope? |
The first, second, fourth and fifth calls to context.send() take place in the same request and so these context variables have the same request scope. In addition the context variable used in the third call to to context.send() has a completely separate transaction scope. |
Do the context variables in the five calls to context.send() use the same JMSContext (and therefore MessageProducer ) objects? |
All five context variables are injected using identical annotatons. The context variables in the first, second, fourth and fifth calls are in the same request scope and so share the same JMSContext (and therefore MessageProducer ) object. The context variable in the third call is in a separate transaction scope and so uses a different JMSContext (and therefore MessageProducer ) object. |
Are the five messages guaranteed to be delivered in the order in which they are sent? | The first, second, fourth and fifth messages share one MessageProducer object and are delivered in order. However the third message uses a different MessageProducer object and so there is no guarantee that the third message will be delivered between the second and fourth messages. |
Case H: JMSContext lifecycle
The JMSContext
object used by the first, second, fourth and fifth calls to context.send()
will be created when the first call to context.send()
takes place, and will be destroyed when the method returns.
The JMSContext
object used by the third call to context.send()
will be created when the third call to context.send()
takes place, and will be destroyed when the transaction is committed
Important note: Although JMS does not define what happens when the same JMSContext
object is used both within and outside a transaction, this ambiguity is avoided when the JMSContext
object is injected because since the two cases have separate scopes and so different JMSContext
objects are always used.
Use case J. Two separate container-managed transactions on the same thread, one suspended before the second is started
Consider two stateless session beans, Bean1
and Bean2
.
Bean1
is configured to use container-managed transactions and has a business method method1
, which is configured to require a transaction. The bean has an injected JMSContext
. method1
uses this context to send a message and then invokes method2
on bean1
. It then sends a further message.
Bean2
is also configured to use container-managed transactions and has a business method method2
, which is configured to require a new transaction. The bean has an injected JMSContext
. method2
simply uses this context to send a message.
A remote client obtains a reference to Bean1
and calls method1
.
This is Bean1
@TransactionManagement(TransactionManagementType.CONTAINER)
@Stateless
public class Bean1 {
@Resource(lookup="jms/inboundQueue") Queue queue;
@Inject
@JMSConnectionFactory("jms/connectionFactory")
JMSContext context;
@EJB Bean2 bean2;
@TransactionAttribute(REQUIRED)
public void method1() {
context.send(queue,"Message 1");
bean2.method2();
context.send(queue,"Message 3");
}
}
This is Bean2
@TransactionManagement(TransactionManagementType.CONTAINER)
@Stateless
public class Bean2 {
@Resource(lookup="jms/inboundQueue") Queue queue;
@Inject
@JMSConnectionFactory("jms/connectionFactory")
JMSContext context;
@TransactionAttribute(REQUIRES_NEW)
public void method2() {
context.send(queue,"Message 2");
}
}
Case J: Analysis
Q | A |
---|---|
Are the context variables in the three calls to context.send() injected using identical annotations? |
Yes. Although the context variable used for the first and third calls has a different declaration from the context variable used for the second call, both declarations have identical annotations. |
What scope do the context variables in the three calls to context.send() have? |
All three calls to context.send() take place within transactions, so both context variables have transaction scope. |
Are the context variables in the three calls to context.send() in the same scope? |
The first and third calls to context.send() take place in one transaction whereas the second call to to context.send() take place in a separate transaction. This means the context variables used in the first and third calls are in one transaction scope, and the context variable used in the second call is in a separate transaction scope. |
Do the context variables in the three calls to context.send() use the same JMSContext (and therefore MessageProducer ) objects? |
All three context variables are injected using identical annotatons. The context variables in the first and third calls are in the same transaction scope and so share the same JMSContext (and therefore MessageProducer ) object. The context variable in the second call is in a different transaction scope uses a different JMSContext (and therefore MessageProducer ) object. |
Are the three messages guaranteed to be delivered in the order in which they are sent? | The first and third messages are sent using the same MessageProducer objects and are guaranteed to be delivered in order. However the second message is sent using a different MessageProducer object and so there is no guarantee that it will be delivered in between the first and third messages. |
Case J: JMSContext lifecycle
The JMSContext
object used by method1
will be created when method1
uses context
for the first time, and destroyed when the first transaction is committed, which will be when method1
returns.
The JMSContext
object used by method2
will be created when method2
uses context
for the first time, and destroyed when the second transaction is committed, which will be when method2
returns.
Use case K. One bean which calls another within the same transaction, but using different connection factories
(Note that this use case is identical to Use case C except that the two beans specify different connection factories).
Consider two stateless session beans, Bean1
and Bean2
Bean1
is configured to use container-managed transactions and has a business method method1
, which is configured to require a transaction. The bean has an injected JMSContext
. method1
uses this context to send a message and then invokes method2
on Bean2
.
Bean2
is also configured to use container-managed transactions and has a business method method2
, which is also configured to require a transaction. The bean also has an injected JMSContext
to Bean1
, but specifies a different connection factory. method2
simply uses this context to send a second message.
A remote client obtains a reference to Bean1
and calls method1
This is Bean1
@TransactionManagement(TransactionManagementType.CONTAINER)
@Stateless
public class Bean1 {
@Resource(lookup="jms/inboundQueue") Queue queue;
@Inject
@JMSConnectionFactory("jms/connectionFactory1")
JMSContext context;
@EJB Bean2 bean2;
@TransactionAttribute(REQUIRED)
public void method1() {
context.send(queue,"Message 1");
bean2.method2();
}
}
This is Bean2
@TransactionManagement(TransactionManagementType.CONTAINER)
@Stateless
public class Bean2 {
@Resource(lookup="jms/inboundQueue") Queue queue;
@Inject
@JMSConnectionFactory("jms/connectionFactory2")
JMSContext context;
@TransactionAttribute(REQUIRED)
public void method2() {
context.send(queue,"Message 2");
}
}
Case K: Analysis
Q | A |
---|---|
Are the context variables in the two calls to context.send() injected using identical annotations? |
No. The two context variables have different declarations which use different annotations: the declaration in Bean1 uses the annotation @JMSConnectionFactory("jms/connectionFactory1") whilst the declaration in Bean2 uses the annotation @JMSConnectionFactory("jms/connectionFactory2") , which is different |
What scope do the context variables in the two calls to context.send() have? |
Both calls to context.send() take place within a transaction, so they both have transaction scope. |
Are the context variables in the two calls to context.send() in the same scope? |
Yes, since the two calls to context.send() take place in the same transaction |
Do the context variables in the two calls to context.send() use the same JMSContext (and therefore MessageProducer ) objects? |
No. Although they are in the same transaction scope they are injected using different annotations. |
Are the two messages guaranteed to be delivered in the order in which they are sent? | No, since they are sent using different MessageProducer objects. |
Case K: JMSContext lifecycle
The JMSContext
object used by method1
will be created when method1
uses context
for the first time, and destroyed when the container commits the transaction, which will be after both methods have returned.
The JMSContext
object used by method2
will be created when method2
uses context
for the first time, and destroyed when the container commits the transaction, which will be after both methods have returned.
Note how specifying different connection factories means that the same injected JMSContext
object cannot be used.