Turn: Use spring JMS to make asynchronous messages simple

Source: Internet
Author: User

Asynchronous Communication processing is an important part of the Service-Oriented Architecture (SOA), because many systems in the enterprise communicate, especially with external systems, asynchronously. Java Message Service (JMS)
Is an API used to write asynchronous message J2EE applications. Use JMS
The traditional message implementation of Apis involves steps such as finding the factory for connecting columns, queue resources, and creating a JMS session before actually sending and receiving messages ).

Spring framework simplifies the development of JMS applications using Jee components (including JMS. It provides a template mechanism to hide typical JMS implementation details, so developers can focus on message processing tasks without worrying about how to create, access, and release JMS resources.

This article describes spring JMS with a simple web application running on the JBoss MQ server.
API and how to use it to process (send and receive) messages asynchronously. I will compare the traditional methods implemented by JMS with the spring JMS implementation methods to show the use of spring
How simple and flexible JMS is to process messages.

Asynchronous messages and SOA

In the real world, most Web requests are processed synchronously. For example, when a user logs on to a website, he or she enters the user name and password, and the server recognizes the login credential. If the authentication is successful
The user enters the site. Here, the login request is processed immediately after it is accepted from the client. Credit card authorization is also an example of synchronous processing; only when the server verifies that the sent credit card number is valid and the customer's
The customer is allowed to continue the next step only after the account has enough credit limit. Let's take a look at the payment and settlement steps in the order processing system. Once the system verifies that the user's credit card information is correct,
If your account has sufficient funds, you do not need to wait until the payment details and transfer are completed. Payment and Settlement are processed asynchronously so that the customer can proceed with the settlement process.

Compared with typical synchronous requests, asynchronous processing is used for requests that take a long time to process. Another example of asynchronous processing is that in the housing loan processing application, the processing is submitted to AUS (automatically
Underwriting
System. After the lender submits a loan application, the mortgage company sends a request to AUS to obtain credit history information. This request requires comprehensive and detailed credit reports, such as the current and past credit reports of the lender.
It takes a long time to get a response from a request to a credit account, recent payments, and other financial details. It is meaningless for a client program to establish a connection to the server and wait for a long response.
. So there is asynchronous communication, that is, once a request is submitted, it is put into the queue and the customer disconnects the server. Then, the aus service extracts the request from a specific queue, processes it, and sends the result message
Put it in another message queue. Finally, the customer program extracts the response result from the message queue and continues to process the historical credit result information.

JMS

If you have used JMS, you will find it is similar to writing JDBC or JCA code. It has sample code for creating or retrieving JMS resources. The sample code must be repeated whenever you need to write a new class to send or receive messages. The steps involved in the traditional JMS implementation are listed below:

1. Create the initial JNDI context;
2. Obtain the queue connection factory from the jndi context;
3. Get the queue from the queue connection factory;
4. Create a session object;
5. Create a sending or receiving object;
6. Use the sending or receiving objects created in part 1 to send or receive messages;
7. After processing the message, close all JMS resources.

As you can see, only step 1 is the step for processing messages. All the other steps are just for managing JMS resources and have nothing to do with actual business needs, but developers have to write and maintain additional step code.

Spring JMS

The Spring framework provides a template mechanism to hide Java
API details. Jee developers can use the jdbctemplate and jnditemplate classes to access backend databases and Jee resources (data sources and connection pools) respectively ). No difference in JMS
. Spring provides the jmstemplate class, so developers do not have to write sample code for JMS implementation. Spring provides the following advantages when developing a JMS application:

1. Provides an abstract API for JMS, which simplifies the use of JMS. For example, access destination (queue or subject) and publish a message to a specific destination.
2. Jee developers do not have to worry about the differences between different versions of JMS (for example, JMS 1.0.2 and JMS 1.1 );
3. Developers do not have to handle JMS exceptions in particular, because Spring provides an unchecked exception for any JMS exception thrown by JMS code.

Once you start using spring in a JMS application, you will enjoy the simplicity of asynchronous message processing. The spring JMS framework provides various Java classes to simplify JMS development.

Table 1: Spring JMS classes

In the subsequent sections, I will explain in detail the classes in table 1 (such as jmstemplate, destinationresolver, and messageconverter ).

# P #

Jmstemplate

Jmstemplate provides several helper methods to perform basic operations. Before using jmstemplate, it is necessary to know which JMS rules the JMS Provider supports
Fan. JBoss as 4.0.2 and WebLogic 8.1 servers support the jms1.0.2 specification. WebLogic Server
9.0 supports jms1.1. Jms1.1 unifies the PTP and pub/sub programming interfaces. With this change, developers can create a transaction session and then create a JMS transaction
From Queue (PTP) to receive and send a message to topic (pub/Sub ). Jms1.1 is backward compatible with jms1.0, so the code written based on jms1.0
Still working with jms1.1.

Jmstemplate provides various methods to receive and send messages. Table 2 is a list of methods.

Table 2: JMS Template Method

Use the JNDI context to store and retrieve the destination. When configuring the spring application context, we use jndiobjectfactorybean to obtain the JMS destination reference.
Destinationresolver is used to resolve the destination name to a JMS destination. It is helpful when the application has many destinations.
Dynamicdestinationresolver (implemented by destinationresolver by default) is used to parse dynamic destinations.

The messageconverter interface defines the contract for conversion between Java objects and JMS messages. With the converter, application code can focus on business objects without worrying about how it works.
Indicates a JMS message. Simplemessageconverter (and simplemessageconverter102) is the default
Messageconverter implementation. They are used to convert string, byte array (byte []), map, and serializable objects into JMS
Textmessage, JMS bytesmessage, JMS mapmessage, and JMS
Objectmessage. You can compile a custom implementation of the messageconverter interface and combine it with XML binding frameworks such as jaxb, Castor,
Commons digester, xmlbeans, or xstream to convert an XML document to textmessage.

Sample Application

I will use a sample Loan Application Processing System (loanproc) to describe how to use spring in JMS applications. Loanproc sends loans as part of loan processing
Details (loan ID, borrower name, borrower's SSN, loan expiration date, and
Loan
Amount) Request credit history from the aus system. To simplify the example, we will obtain credit history details based on two parameters: credit rating and loan quantity. Let's assume that the credit check is handled
The business rules are as follows:

1. If the number of loans is equal to or less than $500,000, the lender must have at least one "good" credit (for example, the lender's credit score is between 680 and 699 );
2. If the number of loans exceeds $500,000, the lender must have at least one "very good" credit, which means that his/her credit score exceeds 700.

Loan Application Use Case

The use case for loan request processing consists of the following steps:

1. on the loan application web page, enter loan details and submit a loan application;
2. The program then sends loan details to the aus system to obtain credit history details. Send a request to the Message Queue named creditrequestsendqueue.
3. The Aus system extracts loan details from the queue and uses loan parameters to retrieve credit history information from the database;
4. The Aus system then creates a new message with the found lender's credit history information and sends it to the Message Queue named creditrequestreceivequeue;
5. Finally, loanproc extracts the Response Message from the receiving message queue and processes the loan application. It determines whether the application is approved or rejected.

In the application, two message queues are configured in the same JBoss MQ server. Use case is shown in sequence 1 as follows:

Figure 1: loan processing application sequence diagram

Technology

Table 3 lists some of the technologies and open-source frameworks used in the example application.

Table 3: framework used in JMS applications

# P #

Use Hermes's JMS resource settings

To process messages asynchronously, we need a message queue to send and receive messages. In JBoss, we use the xml configuration file to create a message queue and use the JMS console to view queue details.
Material. Listing 1 shows the JMS configuration snippet of the XML configuration file. (This part can be added to % jboss_home % \ Server \ All \ deploy-
In the jbossmq-destinations-service.xml file under the hasingleton \ JMS directory .)

List 1: JMS queue configuration in the JBoss MQ Server

<!--  Credit Request Send Queue  -->
<mbean code="org.jboss.mq.server.jmx.Queue"
  name="jboss.mq.destination:service=Queue,name=CreditRequestSendQueue"> 
  <depends optional-attribute-name="DestinationManager">       

jboss.mq:service=DestinationManager 
  </depends></mbean>
<!--  Credit Request Receive Queue  -->
<mbean code="org.jboss.mq.server.jmx.Queue"   

name="jboss.mq.destination:service=Queue,name=CreditRequestReceiveQueue"> 
<depends optional-attribute-name="DestinationManager">     

jboss.mq:service=DestinationManager  </depends>
</mbean>  

Now, let's see how to use a JMS tool called Hermes to browse message queues. Hermes is a Java
Swing application, which can create, manage, and monitor the JMS destination in the JMS provider. Such a JMS provider has jbossmq,
Webspheremq, activemq, and
Arjuna. Download Hermes from the website and decompress the ZIP file to a local directory (for example, c: \ Dev \ tools \ Hermes ). Once installed, double-click
Hermes. BAT (in the bin directory) starts the program.

To configure the jbossmq server in Hermes, refer to the demo on the Hermes site. The JBoss MQ configuration is illustrated step by step.

When you configure a new initial JNDI context, enter the following configuration information.

providerURL = jnp://localhost:1099
initialContextFactory = org.jnp.interfaces.NamingContextFactory
urlPkgPrefixes = org.jnp.interfaces:org.jboss.naming
securityCredentials = admin
securityPrincipal = admin

When creating a new destinations, enter queue/creditrequestsendqueue and queue/creditrequestreceivequeue. Figure 2 shows the main screen of the JMS console, which displays the new message created for the sample JMS application.

Figure 2: screenshots of all destinations in Hermes

Figure 3 Hermes
Message Queue details displayed on the JMS console. You can see that there are five messages in the queue and the console displays the message details, such as Message ID and message
Destination, time stamp, and actual messages.

Figure 3: screenshot of queue details in Hermes

Using spring JMS makes asynchronous messages easy

The message queue names and other JMS and JNDI parameters used in the sample application are shown in table 4 below.

Table 4: Spring JMS configuration parameters

# P #

Spring Configuration

The JMS destinations required to run the sample application is now available in XML
The spring configuration file (called the spring-jms.xml) is time to assemble the details of the JMS component. Use the setter dependency injection principle in IOC design mode to load these components.
Let's take a closer look at the components and display an xml configuration segment for each JMS component.

The JNDI context is the entry for obtaining JMS resources, so we first configure a JNDI template. Listing 2 shows a spring bean named jnditemplate, which has common parameters required to obtain the initial JNDI context.

List 2: JNDI context Template

<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
    <property name="environment">
        <props>
            <prop key="java.naming.factory.initial">               

org.jnp.interfaces.NamingContextFactory
            </prop>
            <prop key="java.naming.provider.url">
                localhost
            </prop>
            <prop key="java.naming.factory.url.pkgs">                                    

          org.jnp.interfaces:org.jboss.naming
            </prop>
        </props>
    </property>
</bean>  

Next, we configure the queue connection factory. Listing 3 shows the queue connection factory.

Listing 3: Connection factory configuration through JMS

<bean id="jmsQueueConnectionFactory"           

class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiTemplate">
        <ref bean="jndiTemplate"/>
    </property>
    <property name="jndiName">
         <value>UIL2ConnectionFactory</value>
    </property>
</bean> 

We define two JMS destinations to send and receive messages. Listing 4 and Listing 5 show these details.

Listing 4: sending queue Configuration

<bean id="sendDestination"
    class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiTemplate">
        <ref bean="jndiTemplate"/>
    </property>
    <property name="jndiName">
        <value>queue/CreditRequestSendQueue</value>
    </property>
</bean>  

Listing 5: receiving queue Configuration

<bean id="receiveDestination"
    class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiTemplate">
        <ref bean="jndiTemplate"/>
    </property>
        <property name="jndiName">
        <value>queue/CreditReqeustReceiveQueue</value>
        </property>
</bean>  

Then, we configure the jmstemplate component. We use jmstemplate102 in the sample application. Use the defaultdestination attribute to specify the JMS destination.

Listing 6: JMS template Configuration

<bean id="jmsTemplate"
       class="org.springframework.jms.core.JmsTemplate102">
    <property name="connectionFactory">
        <ref bean="jmsQueueConnectionFactory"/>
    </property>
    <property name="defaultDestination">
        <ref bean="destination"/>
     </property>
    <property name="receiveTimeout">
        <value>30000</value>
    </property>
</bean>

Finally, we configure the send and receiver components. Listing 7 and 8 show the sender and Cycler object configurations.

Listing 7: JMS sender Configuration

Listing 7. JMS Sender configuration
<bean id="jmsSender" class="springexample.client.JMSSender">
    <property name="jmsTemplate">
        <ref bean="jmsTemplate"/>
    </property>
</bean>  

Listing 8: JMS consumer er Configuration

<bean id="jmsReceiver" class="springexample.client.JMSReceiver">
    <property name="jmsTemplate">
        <ref bean="jmsTemplate"/>
    </property>
</bean>

# P #

Test and monitoring

I used a test class called loanapplicationcontrollertest to test the loanproc application. We use this class to set loan parameters and call the credit request service class.

Let's take a look at the implementation of message senders using traditional JMS instead of spring JMS APIs. Listing 9 shows the sendmessage method of the messagesenderjms class, which has all the required steps to process messages using the jms api.

Listing 9: Traditional JMS implementation

public void sendMessage() {
    queueName = "queue/CreditRequestSendQueue";
        System.out.println("Queue name is " + queueName);
    /*
    * Create JNDI Initial Context
    */
    try {
        Hashtable env = new Hashtable();
        env.put("java.naming.factory.initial",                       

"org.jnp.interfaces.NamingContextFactory");
        env.put("java.naming.provider.url","localhost");
        env.put("java.naming.factory.url.pkgs",                       

"org.jnp.interfaces:org.jboss.naming");
        jndiContext = new InitialContext(env);
    } catch (NamingException e) {
           System.out.println("Could not create JNDI API " +
           "context: " + e.toString());    }
     /*    
     * Get queue connection factory and queue objects from JNDI context.
     */
    try {
        queueConnectionFactory = (QueueConnectionFactory)
        jndiContext.lookup("UIL2ConnectionFactory");
        queue = (Queue) jndiContext.lookup(queueName);
   } catch(NamingException e) {
        System.out.println("JNDI API lookup failed: " +
                       e.toString());
   }
   /*
   * Create connection, session, sender objects.
   * Send the message.
   * Cleanup JMS connction.
   */
    try {
        queueConnection =                                                         

queueConnectionFactory.createQueueConnection();
        queueSession = queueConnection.createQueueSession(false,                           

             Session.AUTO_ACKNOWLEDGE);
        queueSender = queueSession.createSender(queue);
             message = queueSession.createTextMessage();
        message.setText("This is a sample JMS message.");
        System.out.println("Sending message: " + message.getText());                       

        queueSender.send(message);
    } catch (JMSException e) {
        System.out.println("Exception occurred: " + e.toString());
    } finally {
        if (queueConnection != null){
            try {
                queueConnection.close();
            } catch (JMSException e) {}
        }
    }
}

Now let's take a look at the message senders implemented using spring. Listing 10 shows the send method code in the messagesenderspringjms class.

Listing 10: Using spring api jms implementation

public void send() {
    try {
        ClassPathXmlApplicationContext appContext =
            new ClassPathXmlApplicationContext(new String[]
            { "spring-jms.xml"});
                System.out.println("Classpath loaded");
         JMSSender jmsSender = (JMSSender)appContext.getBean("jmsSender");                 

       jmsSender.sendMesage();
        System.out.println("Message sent using Spring JMS.");
    } catch(Exception e) {
        e.printStackTrace();       }
}  

As you can see, all the resource steps related to managing JMS resources are handled by the configuration file of the spring container. We only need to get the jmssender reference and call the sendmessage above it.

Conclusion

In this article, we will see how the Spring framework simplifies the use of JMS
API asynchronous message application development. Spring removes all the sample code required for JMS message processing, such as getting the connection factory, creating queues and session objects from Java code, and using
Configure files to assemble them. Due to this powerful IOC principle, we can dynamically exchange JMS resource objects without modifying Java code.

Because asynchronous messages are part of the overall needs of the SOA framework, spring is very suitable for integration with the SOA tool set. Likewise, JMS management tools such as Hermes make it easy to create, manage, and control JMS resources, especially for system administrators.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.