Upload
c2b2-consulting
View
1.588
Download
3
Tags:
Embed Size (px)
DESCRIPTION
Presentation by Nigel Deakin (Oracle) delivered at the first London GlassFish User Group (GUG) event on the 18th of September 2013. GlassFish 4.0 is the application server to support the new Java EE 7 standard. One of the most significant components of Java EE 7 is JMS 2.0, which is the first revision to the JMS (Java Message Service) API for over a decade and which introduces a new and much simpler API. This talk will review the new features of JMS 2.0 and other recent messaging-related changes in GlassFish 4.0.
Citation preview
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 1
New JMS features in GlassFish 4.0
Nigel Deakin
Oracle
Developer, GlassFish Message Queue
Specification lead, JMS 2.0
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 3
The following is intended to outline our general product direction. It is intended
for information purposes only, and may not be incorporated into any contract.
It is not a commitment to deliver any material, code, or functionality, and should
not be relied upon in making purchasing decisions. The development, release,
and timing of any features or functionality described for Oracle’s products
remains at the sole discretion of Oracle.
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 4
GlassFish 4
GlassFish Server Open Source Edition 4.0
– First Java EE 7 compliant application server
– Includes Open Message Queue 5.0
– Download from http://glassfish.java.net
Open Message Queue 5.0
– First JMS 2.0 compliant messaging system
– Non Java EE users can download from mq.java.net
For "developers to explore and begin exploiting Java EE 7"
Released June 2013
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 5
New messaging features of GlassFish 4
Messaging features unrelated to JMS 2.0
JMS 2.0
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 6
Messaging features unrelated to JMS 2.0
New shared threadpool implementation in broker
– as before, set threadpool_model=shared to enable
– uses Grizzly NIO framework
– supports SSL (previously only for threadpool_model=dedicated)
– shared threads more scalable at a cost to performance
Improved support for DB reconnection with JDBC databases
– in the Message Queue JDBC Connection Pool
C API extended with some new JMS 2.0 features
– shared durable subscriptions, delivery delay
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 7
JMS 2.0
JMS 1.1 (2002)
– dozens of implementations, both standalone and as part of a full Java EE
provider
JMS 2.0 (2013)
– launched in 2011 as JSR 343
– released in 2013 with Java EE 7
– available in Open Message Queue 5.0 (standalone JMS provider) and in
GlassFish 4.0 (full Java EE provider)
– other implementations announced or in progress
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 8
What's new in JMS 2.0
Simpler and easier to use
New messaging features
Better Java EE integration
– define differences between JMS in SE and EE more clearly
– simpler resource configuration
– standardized configuration of JMS MDBs
Minor corrections and clarifications
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 9
JMS 2.0 Simpler and easier to use
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 10
JMS API simplifications
Minor simplifications to existing standard API where it won't break
compatibility
Define new simplified API requiring fewer objects
– JMSContext, JMSProducer, JMSConsumer
– In Java EE, allow JMSContext to be injected and managed by the
container
Twin-track strategy
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 11
The four JMS APIs
Simplified
API
Standard API Legacy
queue-specific
API
Legacy
topic-specific
API
Introduced
in JMS 2.0 JMS 1.1 JMS 1.0 JMS 1.0
Main
interfaces
Connection
Factory
JMSContext
JMSProducer
JMSConsumer
ConnectionFactory
Connection
Session
MessageProducer
MessageConsumer
QueueConnection
Factory
QueueConnection
QueueSession,
QueueSender,
QueueReceiver
TopicConnection
Factory
TopicConnection
TopicSession
TopicProducer
TopicSubscriber
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 12
Why did JMS 1.1 need simplifying?
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 13
JMS 1.1: Sending a message
@Resource(lookup = "java:global/jms/demoConnectionFactory")
ConnectionFactory connectionFactory;
@Resource(lookup = "java:global/jms/demoQueue")
Queue demoQueue;
public void sendMessage(String payload) {
try {
Connection connection = connectionFactory.createConnection();
try {
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session.createProducer(demoQueue);
TextMessage textMessage = session.createTextMessage(payload);
messageProducer.send(textMessage);
} finally {
connection.close();
}
} catch (JMSException ex) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
}
}
13 lines of
code just
to send a
message
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 14
JMS 1.1: Sending a message
@Resource(lookup = "java:global/jms/demoConnectionFactory")
ConnectionFactory connectionFactory;
@Resource(lookup = "java:global/jms/demoQueue")
Queue demoQueue;
public void sendMessage(String payload) {
try {
Connection connection = connectionFactory.createConnection();
try {
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session.createProducer(demoQueue);
TextMessage textMessage = session.createTextMessage(payload);
messageProducer.send(textMessage);
} finally {
connection.close();
}
} catch (JMSException ex) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
}
}
must create
several
intermediate
objects
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 15
JMS 1.1: Sending a message
@Resource(lookup = "java:global/jms/demoConnectionFactory")
ConnectionFactory connectionFactory;
@Resource(lookup = "java:global/jms/demoQueue")
Queue demoQueue;
public void sendMessage(String payload) {
try {
Connection connection = connectionFactory.createConnection();
try {
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session.createProducer(demoQueue);
TextMessage textMessage = session.createTextMessage(payload);
messageProducer.send(textMessage);
} finally {
connection.close();
}
} catch (JMSException ex) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
}
}
redundant
and
misleading
arguments
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 16
JMS 1.1: Sending a message
@Resource(lookup = "java:global/jms/demoConnectionFactory")
ConnectionFactory connectionFactory;
@Resource(lookup = "java:global/jms/demoQueue")
Queue demoQueue;
public void sendMessage(String payload) {
try {
Connection connection = connectionFactory.createConnection();
try {
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session.createProducer(demoQueue);
TextMessage textMessage = session.createTextMessage(payload);
messageProducer.send(textMessage);
} finally {
connection.close();
}
} catch (JMSException ex) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
}
}
boilerplate
code
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 17
JMS 1.1: Sending a message
@Resource(lookup = "java:global/jms/demoConnectionFactory")
ConnectionFactory connectionFactory;
@Resource(lookup = "java:global/jms/demoQueue")
Queue demoQueue;
public void sendMessage(String payload) {
try {
Connection connection = connectionFactory.createConnection();
try {
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session.createProducer(demoQueue);
TextMessage textMessage = session.createTextMessage(payload);
messageProducer.send(textMessage);
} finally {
connection.close();
}
} catch (JMSException ex) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
}
}
must
close
resources
after use!
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 18
JMS 1.1: Sending a message
@Resource(lookup = "java:global/jms/demoConnectionFactory")
ConnectionFactory connectionFactory;
@Resource(lookup = "java:global/jms/demoQueue")
Queue demoQueue;
public void sendMessage(String payload) {
try {
Connection connection = connectionFactory.createConnection();
try {
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session.createProducer(demoQueue);
TextMessage textMessage = session.createTextMessage(payload);
messageProducer.send(textMessage);
} finally {
connection.close();
}
} catch (JMSException ex) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
}
}
all
methods
throw
checked
exceptions
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 19
Minor simplifications to the existing standard API
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 20
Minor simplifications to the standard API
Need to maintain backwards compatibility limits scope for change
New methods on javax.jms.Connection to create a Session:
– Existing method (will remain)
– New method mainly for Java SE
– New method mainly for Java EE
Simpler API to create a Session
connection.createSession(transacted,deliveryMode)
connection.createSession(sessionMode)
connection.createSession()
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 21
Minor simplifications to the standard API
Make JMS objects implement java.jang.AutoCloseable
– Connection
– Session
– MessageProducer
– MessageConsumer
– QueueBrowser
Requires Java SE 7
Simpler API to close JMS objects
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 22
Minor simplifications to the standard JMS API
Make JMS objects implement java.jang.AutoCloseable
– Connection, Session, MessageProducer, MessageConsumer,
QueueBrowser
Simpler API to close JMS objects
@Resource(lookup = "jms/connFactory") ConnectionFactory cf;
@Resource(lookup="jms/inboundQueue")
Destination dest;
public void sendMessage (String payload) throws JMSException {
try ( Connection conn = connectionFactory.createConnection();
Session session = conn.createSession();
MessageProducer producer = session.createProducer(dest);
){
Message mess = sess.createTextMessage(payload);
producer.send(mess);
} catch(JMSException e){
// exception handling
}
}
close() is called
automatically
at end of block
Create closeable
resources in a
try-with-
resources block
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 23
Completely new simplified API
Introducing JMSContext and JMSProducer
@Resource(lookup = "java:global/jms/demoConnectionFactory")
ConnectionFactory connectionFactory;
@Resource(lookup = "java:global/jms/demoQueue")
Queue demoQueue;
public void sendMessageNew(String payload) {
try (JMSContext context = connectionFactory.createContext();){
context.createProducer().send(demoQueue, payload);
} catch (JMSRuntimeException ex) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
}
}
13 lines
reduced
to 5
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 24
Completely new simplified API
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 25
@Resource(lookup = "java:global/jms/demoConnectionFactory")
ConnectionFactory connectionFactory;
@Resource(lookup = "java:global/jms/demoQueue")
Queue demoQueue;
public void sendMessageNew(String payload) {
try (JMSContext context = connectionFactory.createContext();){
context.createProducer().send(demoQueue, payload);
} catch (JMSRuntimeException ex) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, ex);
}
}
Completely new simplified API Introducing JMSContext and JMSProducer
JMSContext
combines
Connection
and Session
Payload
can be
sent
directly
No checked
exceptions
thrown
close() is called
automatically
at end of block
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 26
JMSContext (1/2)
A new object which encapsulates a Connection, a Session and an
anonymous MessageProducer
Created from a ConnectionFactory
Call close() after use, or create in a try-with-resources block
Can also be injected (into a Java EE web or EJB application)
JMSContext context = connectionFactory.createContext(sessionMode);
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 27
JMSContext (2/2)
Can also create from an existing JMSContext
(to reuse its connection – Java SE only)
Used to create JMSProducer objects for sending messages
Used to create JMSConsumer objects for receiving messages
Methods on JMSContext, JMSProducer and JMSConsumer throw only
unchecked exceptions
JMSContext context2 = context1.createContext(sessionMode);
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 28
JMSProducer
Messages are sent by creating a JMSProducer object
– does not encapsulate a MessageProducer so is lightweight
– supports method chaining for a fluid style
JMS 1.1
JMS 2.0
MessageProducer producer = session.createProducer();
producer.send(destination,message);
JMSProducer producer = context.createProducer();
producer.send(destination,message);
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 29
JMSProducer
JMS 1.1
JMS 2.0
Setting message delivery options using method chaining
context.createProducer().setDeliveryMode(DeliveryMode.NON_PERSISTENT).
setPriority(1).setTimeToLive(1000).send(destination,message);
MessageProducer producer = session.createProducer();
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
producer.setPriority(1);
producer.setTimeToLive(1000);
producer.send(destination,message);
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 30
JMSProducer
JMS 1.1 (need to set on the message)
JMS 2.0 (can also set on the JMSProducer)
Setting message properties and headers
context.createProducer().setProperty("foo","bar").send(destination,"Hello");
MessageProducer producer = session.createProducer();
TextMessage textMessage = session.createTextMessage("Hello);
textMessage.setStringProperty("foo","bar");
producer.send(destination,message);
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 31
JMSProducer
Methods on JMSProducer to send a Message
– send(Destination dest, Message message)
No need to create a Message
– send(Destination dest, Map<String,Object> payload)
– send(Destination dest, Serializable payload)
– send(Destination dest, String payload)
– send(Destination dest, byte[] payload)
Use methods on JMSProducer to set delivery options, message
headers and message properties
Sending message bodies directly
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 32
JMSConsumer
Messages are consumed by creating a JMSConsumer object
– encapsulates a MessageConsumer
– similar functionality and API to MessageConsumer
Synchronous
Asynchronous
Connection is automatically started (configurable)
JMSConsumer consumer = context.createConsumer(destination);
Message message = consumer.receive(1000);
JMSConsumer consumer = context.createConsumer(destination);
consumer.setMessageListener(messageListener);
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 33
JMSConsumer Receiving message bodies directly
Methods on JMSConsumer that return a Message
– Message receive();
– Message receive(long timeout);
– Message receiveNoWait();
Methods on JMSConsumer that return message body directly
– <T> T receiveBody(Class<T> c);
– <T> T receiveBody(Class<T> c, long timeout);
– <T> T receiveBodyNoWait(Class<T> c);
When consuming messages synchronously
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 34
JMSConsumer Receiving message payloads directly
public String receiveMessage() throws NamingException {
InitialContext initialContext = getInitialContext();
ConnectionFactory connectionFactory =
(ConnectionFactory) initialContext.lookup("jms/connectionFactory");
Queue inboundQueue = (Queue)initialContext.lookup("jms/inboundQueue");
try (JMSContext context = connectionFactory.createContext();) {
JMSConsumer consumer = context.createConsumer(inboundQueue);
return consumer.receiveBody(String.class);
}
}
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 35
Extracting the body from a message
Old way
New way
In both the standard and simplified APIs
Message message = consumer.receive(1000);
TextMessage textMessage = (TextMessage) message;
String body = textMessage.getText();
Message message = consumer.receive(1000);
String body = message.getBody(String.class);
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 36
Injection of JMSContext objects
into a Java EE web or EJB container
@Inject
@JMSConnectionFactory("jms/connectionFactory")
private JMSContext context;
@Resource(mappedName = "jms/inboundQueue")
private Queue inboundQueue;
public void sendMessage (String payload) {
context.createProducer().send(inboundQueue, payload);
}
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 37
Injection of JMSContext objects
into a Java EE web or EJB container
@Inject
@JMSConnectionFactory("jms/connectionFactory")
private JMSContext context;
@Resource(mappedName = "jms/inboundQueue")
private Queue inboundQueue;
public void sendMessage (String payload) {
context.createProducer().send(inboundQueue, payload);
}
Use @Inject to
inject the
JMSContext,
specifying
connection
factory to use
Container will close
JMSContext
automatically at
end of transaction
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 38
Injection of JMSContext objects Connection factory will default to platform default JMS
Specifying session mode
Specifying user and password (may be aliased)
into a Java EE web or EJB container
@Inject private JMSContext context;
@Inject
@JMSConnectionFactory("jms/connectionFactory")
@JMSSessionMode(JMSContext.AUTO_ACKNOWLEDGE)
private JMSContext context;
@Inject
@JMSConnectionFactory("jms/connectionFactory")
@JMSPasswordCredential(userName="admin",password="mypassword")
private JMSContext context;
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 39
Injection of JMSContext objects
Injected JMSContext objects have a scope
– In a JTA transaction, scope is the transaction
– If no JTA transaction, scope is the request
JMSContext is automatically closed when scope ends
Inject two JMSContext objects within the same scope and you get the
same object
– if @JMSConnectionFactory, @JMSPasswordCredential and
@JMSSessionMode annotations match
– Makes it easier to use same session within a transaction
into a Java EE web or EJB container
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 40
New messaging features
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 41
Delivery delay
Allows a JMS client to schedule the future delivery of a message
New method on MessageProducer
New method on JMSProducer
Sets minimum time in ms from that a message should be retained by
the messaging system before delivery to a consumer
Why? If the business requires deferred processing, e.g. end of day
In both the standard and simplified APIs
public JMSProducer setDeliveryDelay(long deliveryDelay)
public void setDeliveryDelay(long deliveryDelay)
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 42
Async send
Send a message and return immediately without blocking until an
acknowledgement has been received from the server.
Instead, when the acknowledgement is received, an asynchronous
callback will be invoked
New methods on MessageProducer
Feature also available on JMSProducer
Why? Allows thread to do other work whilst waiting for the
acknowledgement
In both the standard and simplified APIs
messageProducer.send(message,completionListener)
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 43
Async send
Application specifies a CompletionListener instance
In both the standard and simplified APIs
public interface CompletionListener {
void onCompletion(Message message);
void onException(Message message, Exception exception);
}
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 44
Better handling of "poison" messages: Make JMSMXDeliveryCount mandatory
JMS 1.1 defines an optional JMS defined message property JMSXDeliveryCount.
– When used, this is set by the JMS provider when a message is received,
and is set to the number of times this message has been delivered
(including the first time). The first time is 1, the second time 2, etc
JMS 2.0 will make this mandatory
Why? Allows app servers and applications to handle "poisonous"
messages better
In both the standard and simplified APIs
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 45
Multiple consumers on a topic subscription
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 46
How topics work in JMS 1.1
Topic Producer
Subscription
Consumer
Each message
is copied to
every
subscription
In JMS 1.1,
each
subscription
has a single
consumer
Subscription may
be persisted
(durable) or
memory-only
(non-durable)
Subscription
Consumer
Subscription
Consumer
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 47
Making topic subscriptions more scalable
In JMS 1.1 a topic subscription can have only one consumer
– only one thread can process messages
– limits scalability
JMS 2.0 introduces shared subscriptions
– a new type of topic subscription which may have multiple consumers
– allows the work of processing messages from a topic subscription to be
shared amongst multiple threads, and multiple JVMs
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 48
Shared subscriptions in JMS 2.0
Topic Producer Consumer
Shared Subscription
Each message
is copied to
every
subscription A shared
subscription
may have
multiple
consumers
Subscription may
be persisted
(durable) or
memory-only
(non-durable)
Unshared subscription
Consumer
Consumer
Consumer
Each message on
the shared
subscription is
delivered to only
one consumer
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 49
JMS 1.1 API for topic subscriptions In the standard API (Session)
Non-durable
subscriptions
createConsumer(
Destination destination)
Creates a new non-durable subscription
Creates a consumer on that subscription
Durable
subscriptions
createDurableConsumer(
Topic topic,
String name)
Looks for an existing durable subscription
for the specified name/ clientId
If no such subscription exists, creates
one
Creates a consumer on that subscription
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 50
JMS 2.0 API for topic subscriptions In both the standard and simplified APIs (Session and JMSContext)
Unshared subscriptions Shared subscriptions
Non-durable
subscriptions
createConsumer(
Destination destination)
createSharedConsumer(
Topic topic, String name)
Durable
subscriptions
createDurableConsumer(
Topic topic, String name)
createSharedDurableConsumer(
Topic topic, String name)
For unshared durable subscriptions, clientId must be set and is used to identify
subscription
For shared subscriptions, clientId is optional. If set, it is used to identify subscription.
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 51
Easier definition of JMS resources in Java EE Joint effort with JSR 342 (Java EE 7 platform)
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 52
Easier definition of JMS resources in Java EE
Java EE and JMS recommend applications should obtain JMS
ConnectionFactory and Destination resources by lookup from JNDI
Keeps application code portable
Creating these resources is a burden on the deployer, and is non-
standard
The problem
@Resource(lookupName = "jms/inboundQueue")
private Queue inboundQueue;
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 53
Platform default connection factory
if you simply want to use the application server's built-in JMS provider,
with no special settings:
Making the simple case simple
@Resource(lookup="java:comp/defaultJMSConnectionFactory")
ConnectionFactory myJMScf;
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 54
Easier definition of JMS resources in Java EE
Application may specify the JMS connection factories and JMS
destinations that it needs using annotations
New feature in Java EE 7
@JMSDestinationDefinition(
name = "java:global/jms/myQueue",
interfaceName = "javax.jms.Queue",
destinationName = "demoQueue"
)
@JMSConnectionFactoryDefinition(
name="java:global/jms/myCF"
)
JNDI
name
JNDI
name
queue/
topic
name
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 55
Easier definition of JMS resources in Java EE
Can specify additional standard or provider-specific properties
New feature in Java EE 7
@JMSDestinationDefinition(
name = "java:global/jms/myQueue",
interfaceName = "javax.jms.Queue",
destinationName = "demoQueue"
)
@JMSConnectionFactoryDefinition(
name="java:global/jms/myCF",
maxPoolSize = 30,
minPoolSize= 20,
properties = {
"addressList=mq://localhost:7676",
"reconnectEnabled=true"
}
)
standard
properties
non-
standard
properties
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 56
Easier definition of JMS resources in Java EE
Multiple definitions of same type must be wrapped in collection
annotations (due to restriction in how Java annotations work)
New feature in Java EE 7
@JMSDestinationDefinitions({
@JMSDestinationDefinition(
name = "java:global/jms/myQueue1",
interfaceName = "javax.jms.Queue",
destinationName = "demoQueue1"
),
@JMSDestinationDefinition(
name = "java:global/jms/myQueue2",
interfaceName = "javax.jms.Queue",
destinationName = "demoQueue2"
)
})
@JMSConnectionFactoryDefinitions({
@JMSConnectionFactoryDefinition(
name="java:global/jms/myCF1"
),
@JMSConnectionFactoryDefinition(
name="java:global/jms/myCF2"
)
})
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 57
Easier definition of JMS resources in Java EE
Alternatively application may specify the JMS connection factories and
JMS destinations that it needs in the XML deployment descriptor
New feature in Java EE 7
<jms-destination>
<name>
java:global/jms/myQueue
</name>
<interface-name>
javax.jms.Queue
</interface-name>
<destination-name>
demoQueue
</destination-name>
</jms-destination>
<jms-connection-factory>
<name>java:global/jms/myCF</name>
<max-pool-size>30</max-pool-size>
<min-pool-size>20</min-pool-size>
<property>
<name>addressList</name>
<value>mq://localhost:7676</value>
</property>
<property>
<name>reconnectEnabled</name>
<value>true</value>
</property>
</jms-connection-factory>
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 58
Easier definition of JMS resources in Java EE
Application uses annotations to specify the JMS connection factories
and JMS destinations that it needs using annotations
Deployer uses deployment descriptor elements to define additional
deployment-specific or non-standard requirements
Application server uses both together to create resources automatically
when application is deployed
Additional steps may be needed to physically provision the required
resources
The JMS equivalent to @DataSourceDefinition annotations
Suggested usage
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 59
Easier definition of JMS resources in Java EE
Resources configured in this way must be in one of the following
namespaces:
– java:comp – may be used within same component only
– java:module – may be used within same module only
– java:app – may be used within same applicationonly
– java:global – may be used within any application
May be referenced just like any other resource (e.g. @Resource)
Available namespaces
@Resource(lookup="java:global/jms/myCF")
ConnectionFactory myCF;
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 60
More standardized configuration of JMS MDBs Joint effort with JSR 345 (EJB 3.2)
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 61
More standardized configuration of JMS MDBs
Configuration of JMS MDBs is surprisingly non-standard
EJB 3.1 does not define how to specify
– JNDI name of queue or topic (using annotation)
– JNDI name of connection factory
– clientID
– durableSubscriptionName
EJB 3.1 does not define how topic messages delivered to clustered
MDBs
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 62
More standardized configuration of JMS MDBs
Can also be configured in ejb-jar.xml
New activation property to specify the queue or topic
@MessageDriven(activationConfig = {
@ActivationConfigProperty(
propertyName = "destinationLookup",
propertyValue = "jms/myTopic"),
. . .
})
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 63
More standardized configuration of JMS MDBs
Can also be configured in ejb-jar.xml
New activation property to specify the connection factory
@MessageDriven(activationConfig = {
@ActivationConfigProperty(
propertyName = "connectionFactoryLookup",
propertyValue = "jms/myCF"),
. . .
})
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 64
More standardized configuration of JMS MDBs
Surprisingly, these have never been standardized before
New activation properties to specify durable subscriptions
@MessageDriven(activationConfig = {
@ActivationConfigProperty(
propertyName = "subscriptionDurability",
propertyValue = "Durable"),
@ActivationConfigProperty(
propertyName = "clientId",
propertyValue = "myClientID"),
@ActivationConfigProperty(
propertyName = "subscriptionName",
propertyValue = "MySub"),
. . .
})
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 65
Easier configuration of durable subscriptions
No need to specify clientId and subscription name
@MessageDriven(activationConfig = {
@ActivationConfigProperty(
propertyName = "subscriptionDurability",
propertyValue = "Durable"),
@ActivationConfigProperty(
propertyName = "clientId",
propertyValue = "myClientID"),
@ActivationConfigProperty(
propertyName = "subscriptionName",
propertyValue = "MySub"),
. . .
})
clientId no
longer
required for
durable
subscriptions
if subscription
name is omitted,
the container
generates a
suitable name
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 66
What didn’t make it into JMS 2.0?
Batch delivery
– Delivering multiple messages at a time to async message listeners
– Defer until we have a more comprehensive MDB revamp
Topic delivery in clustered application servers
– In a clustered app server, does each app server instance receive a
separate copy of each message?
– Unclear how a RA could implement this portably
Requiring JMS providers to provide a resource adapter
– Insufficient support, considered inappropriate
Features that were dropped at a late stage
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 67
What’s new in JMS 2.0
Simplicity and ease of use
New messaging features
– multi-threaded topic subscribers
– delivery delay
– async send
Better Java EE integration
– simpler resource configuration
– standardized configuration of JMS MDBs
Minor corrections and clarifications
Summary
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 68
Where to find out more
Visit the JMS 2.0 page at jms-spec.java.net for
– information on the new features in JMS 2.0
– where to download the reference implementations
– where to download example code
– links to the specification and API docs
– various introductory articles about JMS 2.0
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 69
Try JMS 2.0
JMS 2.0 in a standalone provider (for Java SE applications)
– Open Message Queue 5.0
– mq.java.net/
JMS 2.0 in a full Java EE 7 application server
GlassFish 4.0
glassfish.java.net/
Other implementations as they are released
JMS 2.0, EJB 3.2 and Java EE 7
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 70
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 71