'New JMS features in GlassFish 4.0' by Nigel Deakin

71
Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 1

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.

Transcript of 'New JMS features in GlassFish 4.0' by Nigel Deakin

Page 1: 'New JMS features in GlassFish 4.0' by Nigel Deakin

Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 1

Page 2: 'New JMS features in GlassFish 4.0' by Nigel Deakin

New JMS features in GlassFish 4.0

Nigel Deakin

Oracle

Developer, GlassFish Message Queue

Specification lead, JMS 2.0

Page 3: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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.

Page 4: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 5: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 6: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 7: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 8: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 9: 'New JMS features in GlassFish 4.0' by Nigel Deakin

Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 9

JMS 2.0 Simpler and easier to use

Page 10: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 11: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 12: 'New JMS features in GlassFish 4.0' by Nigel Deakin

Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 12

Why did JMS 1.1 need simplifying?

Page 13: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 14: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 15: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 16: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 17: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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!

Page 18: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 19: 'New JMS features in GlassFish 4.0' by Nigel Deakin

Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 19

Minor simplifications to the existing standard API

Page 20: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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()

Page 21: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 22: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 23: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 24: 'New JMS features in GlassFish 4.0' by Nigel Deakin

Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 24

Completely new simplified API

Page 25: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 26: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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);

Page 27: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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);

Page 28: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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);

Page 29: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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);

Page 30: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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);

Page 31: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 32: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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);

Page 33: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 34: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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);

}

}

Page 35: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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);

Page 36: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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);

}

Page 37: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 38: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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;

Page 39: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 40: 'New JMS features in GlassFish 4.0' by Nigel Deakin

Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 40

New messaging features

Page 41: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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)

Page 42: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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)

Page 43: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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);

}

Page 44: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 45: 'New JMS features in GlassFish 4.0' by Nigel Deakin

Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 45

Multiple consumers on a topic subscription

Page 46: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 47: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 48: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 49: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 50: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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.

Page 51: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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)

Page 52: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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;

Page 53: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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;

Page 54: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 55: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 56: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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"

)

})

Page 57: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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>

Page 58: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 59: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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;

Page 60: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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)

Page 61: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 62: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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"),

. . .

})

Page 63: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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"),

. . .

})

Page 64: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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"),

. . .

})

Page 65: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 66: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 67: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 68: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 69: 'New JMS features in GlassFish 4.0' by Nigel Deakin

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

Page 70: 'New JMS features in GlassFish 4.0' by Nigel Deakin

Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 70

Page 71: 'New JMS features in GlassFish 4.0' by Nigel Deakin

Copyright © 2013, Oracle and/or its affiliates. All rights reserved. 71