JMS and dependency injection

JMS 2.0 is a major improvement because the specification leverages Java annotations. The standard also recognizes the advanced features of the Java EE 7 platform. In particular, JMS is designed to integrate with CDI, EJB, and other new endpoints.

Injecting CDI beans

JMS 2.0 supports context and dependency injection through injection of the JMSContext. We have already seen examples. It is also possible to inject the connection factory and then create a context.

Here is a code snippet that demonstrates this technique:

class XMLPublisher {
  @Resource(mappedName="xmlQueueConnectionFactory")
  ConnectionFactory queueConnectionFactory;

  @Resource(mappedName="xmlQueue")
  Queue queue;
  
  private static Logger logger = 
    Logger.getLogger(XMLPublisher.class)

  public void sendXML(XMLDocument doc) {
    try (JMSContext context = 
      queueConnectionFactory.createContext();) {
      context.send(queue, doc.getText());
    }
    catch( JMSRuntimeException e) {
      logger.error(
        "unable to sent message doc: "+
        doc.getId(), e);
    }
  }
}

In the sendXML() method of this XMLPublisher class, we take full advantage of the recent try-acquire-release statement and the AutoClosable type of the JMSContext to ensure that we always close the context. We also trap any unchecked exception to record to a log system that exists somewhere in the application.

The CDI container is used to inject into the connection factory object and also the destination with @Resource.

Injection of JMSContext resources

The injection of JMSContext objects can also be customized more precisely. It is possible to configure the connection factory name, but we can also control the session mode and also the login security credentials.

Here is a code snippet that applies a session mode and login to the connection:

@Inject 
@JMSConnectionFactory("jms/fastQConnectionFactory")
@JMSSessionMode(JMSContext.DUPS_OK_ACKNOWLEDGE)
@JMSPasswordCredential(userName="admin",password="sinc3r3")
private JMSContext context;

The annotation @javax.jms.JMSSessionMode specifies the session connection mode for the channel. The default value is JMSContext.AUTO_ACKNOWLEDGE, and hence this annotation is only applied to connections that do not acknowledge automatically.

The annotation @javax.jms.JMSPasswordCredential specifies user login credentials for a secure connection.

The injected JMSContext has a scope when the application runs inside a Java EE application server or EJB container:

  • If the injected JMSContext instance is a part of a JTA transaction, then the scope will be transactional
  • If the injected JMSContext instance is not part of a JTA transaction, then the scope is a request

The application server also automatically manages the lifetime of the JMSContext; it has the responsibility for closing the context. The server will also inject a shared JMSContext instance if it knows that the connection factory, session mode, and also the security credentials are the same.

A Java EE application using an injected JMSContext from the CDI container is prohibited from calling certain methods on this object instance. These methods may cause undesired behavior, and they are start(), stop(), commit(), rollback(), recover(), acknowledge(), and setExceptionListener().

Injecting EJB beans

The JMS client has full access to enterprise beans if it is run inside a Java EE application server or EJB container. Many Java EE applications already make use of message-driven beans and call other EJBs.

In the web profile, using JMS and EJB are considered extensions, and therefore your application is more responsible for configuration of the infrastructure. Therefore, from an architectural point-of-view, your application might be more at risk from vendor lock-in, especially if you lean on proprietary and non-open source features. However, usually a very good architect and lead designer can abstract certain features away into a critical corner of the application architecture.

Sometimes you have no choice in this matter because the business wants a specific profile and the Java EE standard does not support the functionality that the requirements need.

Definition of JMS resources in Java EE

In JMS 2.0, supporting providers are allowed to optionally implement the JMS Resource by definition annotations. Much of this work was left over from the aborted attempt to move Java EE 7 to the cloud-computing platform, and these existing annotations remain implemented in the reference implementation GlassFish 4.0.

There are two annotations: @javax.jms.JMSConnectionFactoryDefinition and @JMSDestinationDefinition. They define inside an application source code the connection factory and message destination respectively.

Here is a code snippet of the two annotations:

@JMSConnectionFactoryDefinition(
   name="java:global/jms/demoConnectionFactory",
   interfaceName="javax.jms.ConnectionFactory",
   description="Demo connection factory",
   user="admin",
   password="sinc3r3",
   transaction=true,
   maxPoolSize=25, minPoolSize=1)
 public class WebEndpoint { /* ... */ } 
    
@JMSDestinationDefinition(
   name="java:global/jms/demoQueue",
   interfaceName="javax.jms.Queue",
   description="Demo connection factory",
   destinationName="demoQueue" )
public class DataEndpoint { /* ... */ } 

The properties name, interfaceName, description, and destinationName are relatively comprehensible and are equivalent to the configuration for administrative objects.

Some of the properties are optional or default such as clientId, resourceAdaptor, user, password, and transaction.

Some of the properties such as maxPoolSize and minPoolSize are vendor specific.

The original idea for these two annotations was to automatically provision a Java Servlet and an EJB with a connection without requiring information to be set in an XML descriptor file. The provisioning of the resource would have taken place in a PaaS environment.

Incidentally, you can make use of the @javax.jmx. JMSDestinationDefinitions for annotating an array of definitions on a Servlet, EJB, or any other Java EE managed object.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.58.51.36