Abstract:For today's e-commerce, communication between distributed heterogeneous systems has become an inevitable demand. Now, with the emergence of Java Message Service (JMS) and other message standards, it is very easy to develop a loosely coupled synchronous or asynchronous communication distributed system (for exchanging business data and events.
This article describes how to use JMS and message-driven beans (MDB) for message transmission, especially the enterprise message transmission details. This article also introduces the messaging function and configuration settings of the glassfish application server. To better illustrate these technologies, we will discuss a simple real-time application case and its implementation details here.
I. message transmission
In short, message transmission is a communication between the two parties. Enterprise messaging can be defined as communication between two software components or applications. Message transmission is as simple as sending a physical mail. The mail sender prepares good news, gives the correct mailing address, and then selects the correct mailing service. In enterprise message transmission, there must also be a message sender who sends messages to the destination in a specific format. The destination is Message Oriented Middleware or message queue that helps exchange messages. In addition, there must also be a user who synchronously or asynchronously receives messages from the destination. It does not force the sender and receiver to be online at the same time, nor require them to know each other before they can exchange information.
The key benefit of the message passing system is to keep the distributed system loosely coupled. Loose coupling makes the message passing solution different from other tightly coupled communication solutions (for example, remote method invocation and RMI) common Object Request Broker Architecture (CORBA ).
Ii. JMS message transmission
Java messaging service is a message passing API built on Java 2 Platform Enterprise Edition (Java 2 platform, Enterprise Edition, Java ee. It defines a set of common interfaces for creating, sending, and receiving messages.
2.1. JMS supports two message transmission modes
1. Point-to-Point Mode
The point-to-point message transmission mode depends on the concept of message queue, that is, writing the Message address to a specific destination called a queue. The receiver uses the message from the queue to process the message, and then confirms that the message is received. The main features of the point-to-point message transmission mode include:
1) Each message has a user;
2) There is no time dependency between the sender and receiver.
2. Publishing-subscription Mode
In the publish-subscribe mode, a message address is written to a destination called a topic. The message generator publishes a message and the user subscribes to the message. The main features of this message transmission mode include:
1) Each message has multiple users;
2) there is a time dependency between the sender and the receiver, that is, the user must actively accept the message. Even if the subscriber is suspended, the jms api allows the subscriber to create a persistent subscription method to receive messages. With the persistent subscription method, the JMS provider keeps the subscribed message until it receives the request to cancel the subscription or the subscription expires.
2.2 Message Type
JMS supports five message types:
1) Text: a simple text message or a java. Lang. String object.
2) object: serializable (serializable) Java object.
3) byte: A simple byte stream.
4) ing table: A group of names-a set of value pairs.
5) Data Stream: original value data stream.
3. Message-driven beans (MDB)
Message-driven bean helps to process messages asynchronously. MDB acts as the listener for JMS messages. The JMS client cannot find the MDB and directly call the method. On the contrary, the client sends the message to the destination where the MDB is listening. When a message is received, the EJB container calls the onmessage method of MDB. In this method, messages are usually converted to one of the five JMS message types and processed as the business logic of the application. MDB runs in asynchronous mode and is stateless and transaction-aware. These features make MDB more scalable and provide a robust solution for enterprises to send messages.
Iv. JMS support in glassfish
Glassfish is an open source application server for developing and deploying Java EE applications and Web services. This server is compatible with Java Enterprise Edition 5 (Java ee 5) and is actually a reference implementation of Java ee 5.
Glassfish provides great support for JMS message delivery by providing a fully integrated JMS provider. The Java Message Service API integrates the Sun Java System Message Queue software into glassfish and provides transparent JMS message delivery support.
4.1. glassfish supports two kinds of JMS resources: Connecting factory and destination resources:
1. The connection factory is an object used by the JMS client to create a connection to the JMS provider. There are three connection factory types:
1) connection Factory: it is used by the point-to-point and publish-subscribe message transmission mode.
2) queue connection Factory: Used in point-to-point message transmission mode.
3) topic connection Factory: Used in publish-subscribe message transmission mode.
2. The destination is an object. The JMS message generator uses this object to mail messages to this object. It is also a resource where the JMS message consumer uses messages from this resource. Supported destination types include:
1) queue: the queue is the destination of point-to-point communication.
2) topic: the topic is the destination of publish-subscribe communication.
3) topic connection Factory: Used in publish-subscribe message transmission mode.
4.2. Some JMS connection functions supported by glassfish
1. Connection Pool
The glassfish server automatically collects JMS connections. You can use the glassfish console or asadmin command to set connection pool properties. Configure the connection pool details when creating a connection factory. Some connection pool parameters supported by glassfish include:
Initial and minimum values of the Connection Pool: indicates the number of initial connections in the connection pool. This is also the minimum number of connections set for the connection pool.
Maximum connection pool: indicates the maximum number of available connections in the connection pool.
Number of connections in the connection pool: the number of connections that should be removed when the connection pool reaches idle timeout.
Idle Timeout: the maximum time for idle connections in the connection pool.
Maximum waiting time: the maximum waiting time before the sending connection times out.
Failed operation: in the case of a failed operation, the connection may be interrupted and then reconnected.
Transaction support: the level of transaction support. The types of transactions supported include "local transactions", "xa transactions", and "no transactions ".
Connection verification: If this attribute is selected, verify the connection before passing it to the application.
2. Connection failover
If the connection is lost, this function enables the application server to reconnect to the Message proxy. If reconnect is enabled and the initial message proxy cannot be connected, the application server attempts to reconnect to another available proxy. You can configure the interval between the number of retries and the number of retries.
5. Access the JMS Resources in the Application
In glassfish, you can access the connection factory and destination in two ways: Use the Java Naming and Directory Interface (Java Naming and directory interfacez, JNDI) to find or use annotations.
5.1. JNDI search
The JMS client uses the jndi api to find the connection factory and Message destination.
InitialContext jndi = new InitialContext();// Lookup queue connection factoryQueueConnectionFactory qFactory = (QueueConnectionFactory)jndi. lookup("webTrackerConnFactory");// Lookup queueQueue queue = (Queue)jndi.lookup("webTrackerQueue");
Note:
Java SE 5.0 introduced annotations, which are declarative styles of programming. Annotations, like meta tags, can be applied to classes, constructors, methods, variables, and so on.
Annotation @ resource is used to find the connection factory and destination. In a web application, if the annotation is placed on a variable, the servlet container injects the requested resource. That is, annotation variables are pre-filled with appropriate values before they are provided for the request.
@Resource(name="connFactory", mappedName="webTrackerConnFactory")private QueueConnectionFactory qFactory;@Resource(name="jmsQueue", mappedName="webTrackerQueue")private Queue queue;
Enable normal message transmission
Vi. Real-time application case analysis
So far, we have discussed how to run JMS and MDB together to implement asynchronous message transmission. We also learned about the functions of glassfish and its jms support. Now we will learn how to use these technologies with the help of real-time application cases called "Web Access tracker.
6.1 case overview:
Web Access tracker helps site administrators or business users monitor user request statistics, such as the number of visits per day, frequently accessed pages, page/service request time, and service request time. In the next section, I will explain a solution to collect access information for each web page accessed by users without compromising the performance of actual applications. You can download the complete resource code of this sample and its deployable binary files from the reference link.
6.2. Solution
With the help of other technologies (such as the Java XML binding architecture, Java Server faces (JSF), Servlet filter, and so on), select the JMS-based message passing solution to capture and process web access data. Glassfish provides support for JMS message transmission and application deployment.
The demo application uses the servlet filter to intercept user requests and extract the required information from the request message header. The message is then sent to the Message Queue as a JMS message. The message is asynchronously transmitted by the message-driven bean JMS message consumer. Data collected from messages will be permanently stored in the XML data storage area. Jaxb is the preferred technology for accessing and storing data to XML files. Use JSF to develop the user interface.
6.3 System Requirements
Java ee 5; glassfish application server; other library files: Apache server commons-beanutils.jar, commons-collections.jar, and commons-logging.jar files
6.4 servlet Filter
Servlet filters can filter requests sent to resources, filter responses from resources, or execute filtering tasks for both. You can write your own filters on the filter page. The main method in this interface is to execute the dofilter Method for core filtering behaviors. You can also implement initialization and destruction methods in the filter class. These methods are called by the servlet container to initialize and destroy the filter.
In the example, the application uses a servlet filter called webtrackerfilter to capture request information, that is, the URL of the requested page, Host IP address, request time, and so on. The information collected from the request will be sent to the Message distributor as a data transfer object (DTO) for further processing.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) request; HttpServletResponse httpServletResponse = (HttpServletResponse) response; // Extract required header parameters and set it in DTO RequestData data = new RequestData(); data.setQueryString(request.getQueryString()); data.setRemoteAddress(request.getRemoteAddr()); data.setRequestURI(request.getRequestURI()); data.setResponseTime(elapsedTime); data.setUserAgent(request.getHeader("User-Agent")); // send the data to message dispatcher messagedispatcher.sendRequestData(data); chain.doFilter(httpServletRequest, httpServletResponse); }
Configure servlet filter:
We have learned how to write a custom filter program. Now we need to configure the filter class in the descriptor deployed by the web application, that is, the Web. xml file. The filter class can be configured by adding the <filter> element in the deployment descriptor file. This element creates the name of the filter and the name of the filter implementation class. You can use the <filter-mapping> element to map the servlet/URL mode to the filter. This will cause webtrackerfilter to be called by all requests in URL mode *. html. The following elements show how to configure webtrackerfilter.
<filter> <filter-name>WebTrackerFilter</filter-name> <filter-class>demo.webtracker.filter.WebTrackerFilter</filter-class></filter><filter-mapping> <filter-name>WebTrackerFilter</filter-name> <url-pattern>*.html</url-pattern></filter-mapping>
6.5 asynchronous message transmission
Use webtrackerfilter to obtain request information. The next step is to develop a JMS client to mail data to the message queue in the form of a JMS message. Select the point-to-point mode for message transmission.
The code snippets developed for typical JMS clients are as follows. You need to use the JMS management object initialcontext retrieved from the JNDI tree to perform the JNDI lookup operation for the connection factory and destination. Another option is to use annotations to inject JMS resources at runtime. The webtrackerconnfactory and webtrackerqueue used in the Code are the JNDI names of the connection factory and the destination respectively. The client assumes that these resources have been configured in glassfish, the configuration must be completed before the code is executed. Refer to "Configure JMS in glassfish"
Resources to learn how to configure JMS resources in glassfish.
Use the createqueueconnection method on the connection factory to create a connection to the JMS service provider ). The Connection provides access to basic message transmission.
The next task is to use the createsession method to create a JMS Session on the connection object ). A session is a single-thread context that generates and uses messages. The first parameter of createsession determines whether to execute the JMS session. The second parameter indicates the message confirmation mode. In this example, the session is automatically confirmed when the message is received instead of being executed.
You must also create a messageproducer that sends messages to the destination. The last step is to create a JMS objectmessage and set the request data to a message. Then, the message is sent to the message queue.
// Get queue connection factoryQueueConnectionFactory qFactory = (QueueConnectionFactory)jndi. lookup("webTrackerConnFactory");// Get queueQueue queue = (Queue)jndi.lookup("webTrackerQueue");// Get queue connectionQueueConnection qConn = (QueueConnection)qFactory. createConnection();// Get sessionSession session = qConn.createSession(false, Session.AUTO_ACKNOWLEDGE);// Set the JMS messageObjectMessage msg = session.createObjectMessage();msg.setObject(data);// Send JMS messagesession.createProducer(jmsLoc.getMessageQueue()).send(msg);
6.6 message-driven beans
The message-driven bean serves as the listener for JMS messages. When a message arrives in the queue, the container calls the onmessage () method of MDB. This method converts a message to the original data message type (that is, objectmessage), then formatted and permanently saved to the data storage area. MDB implements the messagedrivenbean interface and messagelistener interface supported by message types (Optional). That is, if bean supports JMS, javax. JMS. messagelistener is the interface to be implemented.
The following code is used to receive a JMS message:
public void onMessage(Message message) { if (message instanceof ObjectMessage) { RequestData data = (RequestData)((ObjectMessage)message). getObject(); // persist data }}
If you are using Java ee 5, MDB can use @ messagedriven annotations for comments. The comment contains a mappedname element that specifies the JNDI name of the message queue to be listened on by the bean. MDB can use the @ resource annotation to inject messagedrivencontext resources. In this case, you do not have to declare the bean details of the EJB deployment descriptor. The first few lines of MDB are as follows:
@MessageDriven(mappedName = "webTrackerQueue")public class WebTrackerEJB implements MessageListener {/** Context for the MDB. */@Resourceprivate MessageDrivenContext mdbContext;.........
6.7 Java XML binding architecture (jaxb)
Data captured from user requests can be permanently stored in the data storage area. For simplicity, the XML data storage area has been selected in this example. Jaxb is the preferred technology for decoding and organizing XML documents. Jaxb provides a convenient way to access and process XML content by binding the XML schema to a Java representation and using a Java object. The Java object in XML can be created according to the following steps:
1. Prepare the XML structure of the data storage area:
Create an XML schema definition (XSD ). Refer to the webAccess-sample.xml and WebAccess. XSD files provided in the WebTracker-src/config directory to find more details about the XML data storage areas and schema definitions used in this example.
Use the xjc command of jaxb to generate the Java file required to provide XSD. The <glassfish_root>/bin directory contains the xjc. BAT file.
2. XML document decoding:
Data decoding is the process of creating an object tree from an XML document. To edit an XML document, you must create a jaxbcontext. Jaxbcontext provides the abstraction for managing XML/Java binding information. The Java package containing the mode derived class should be passed as a parameter to create jaxbcontext. The XML unconsortor created using jaxbcontext can be used to retrieve the root element of an XML document.
The code for uncompiling an XML data file is as follows:
// create a JAXBContextJAXBContext jc = JAXBContext.newInstance ("demo.webtracker.xmlgen");// create UnMarshallerUnmarshaller unmarshaller = jc.createUnmarshaller();JAXBElement rootElement = (JAXBElement)unmarshaller.unmarshal (new FileInputStream(xmlDataStorePath));// Get the root elementWebAccess access = (WebAccess)rootElement.getValue();
6.8 XML document grouping
The process of grouping is to create an XML document from the content tree. To group XML documents, you must create jaxbcontext. The code used to group XML data files is as follows:
// create a JAXBContextJAXBContext jc = JAXBContext.newInstance ("demo.webtracker.xmlgen");// create a Marshaller and marshal to webAccessLog.xmlMarshaller marshaller = jc.createMarshaller();// Converts java object to XML datamarshaller.marshal(accessData, new File(xmlDataStorePath));
6.9 configure JMS resources in glassfish
If the JMS client needs to send messages to the destination, the resources connecting the factory and destination need to be configured in glassfish. These resources can be created on the glassfish console or by running the asadmin command.
1. Create a JMS connection Factory
The JMS connection factory allows applications to programmatically create other JMS objects. Use the console to configure a connection to the factory by following these steps:
Log on to the glassfish console.
Expand the resources-> jmsresources menu from the navigation bar on the left.
Select the connection factories node.
Click new to create a new connection factory.
Enter the following content:
Use "webtrackerconnfactory" as the JNDI name ). This is the unique JNDI name of the connection factory. The JMS client uses this name to find the connection factory. The JNDI name can contain up to 255 characters, and must contain only letters, numbers, underscores, dashes, or dots.
Use "javax. JMS. queueconnectionfactory" as the resource type ). In the sample application, we have selected the point-to-point message transmission mode, so the resource type should be queueconnectionfactory.
Use "WebTracker connection factory" as the description name.
Click OK.
2. Create a JMS Message Queue
Log on to the glassfish console.
Expand the resources-> jmsresources menu from the navigation bar on the left.
Select destination resources.
Click new to create a destination.
Enter the following content:
Use "webtrackerqueue" as the JNDI name (JNDI name ). This is the unique JNDI name of the destination. The JMS client uses this name to find the message queue.
Use "webtrackerqueue" as the physical destination. This is the destination name in the message proxy.
Use "javax. JMS. queue" as the resource type. Since we use the point-to-point mode, the resource type should be Queue (Queue ).
Use "WebTracker queue destination" as the description name.
Click OK.
3. Deploy applications in glassfish
Package an application as an enterprise application archive (EAR) file consisting of a web module and an EJB module. The web module processes the user interface of the application. Package the message-driven bean and other data handler classes as the EJB module. The following steps explain the deployment of the sample application in glassfish.
Log on to the glassfish console.
Select Applications> enterprise applications from the navigation bar on the left.
Click deploy to deploy the WebTracker application.
Browse the WebTracker. Ear file and upload it.
Click OK.
Copy the WebAccess. xml file in WebTracker-src/config to any local directory. Add a system property called xmlstore. Path and point it to this directory. You can choose Application Server> JVM Settings> JVM Options> Add JVM option from the glassfish console to set system properties. The sample entry is-dxmlstore. Path = C:/temp/webaccesslog. xml.
4. deployment descriptor ejb-jar.xml
The ejb-jar.xml deployment descriptor for the sample application is shown below: You must declare webtrackerejb as a message-driven bean and use javax. JMS. queue as the type of message destination. If you have commented on MDB in Java ee 5, you can ignore this configuration.
<?xml version="1.0" encoding="UTF-8"?><ejb-jar version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"> <display-name>Web Tracker App</display-name> <enterprise-beans> <message-driven> <display-name>WebTrackerEJB</display-name> <ejb-name>WebTrackerEJB</ejb-name> <ejb-class>demo.webtracker.ejb.WebTrackerEJB</ejb-class> <transaction-type>Container</transaction-type> <message-destination-type> javax.jms.Queue </message-destination-type> </message-driven> </enterprise-beans> <assembly-descriptor> <container-transaction> <method> <ejb-name>WebTrackerEJB</ejb-name> <method-name>*</method-name> </method> <trans-attribute>Required</trans-attribute> </container-transaction> </assembly-descriptor></ejb-jar>
Sun-ejb-jar.xml
The sun-ejb-jar.xml deployment descriptor for the sample application is as follows: The JNDI name for the connection factory and queue will be declared in the descriptor. If you have commented on MDB in Java ee 5, you can ignore this configuration.
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE sun-ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 EJB 3.0//EN""http://www.sun.com/software/appserver/dtds/sun-ejb-jar_3_0-0.dtd"><sun-ejb-jar> <enterprise-beans> <ejb> <ejb-name>WebTrackerEJB</ejb-name> <jndi-name>webTrackerQueue</jndi-name> <mdb-connection-factory> <jndi-name>webTrackerConnFactory</jndi-name> </mdb-connection-factory> </ejb> </enterprise-beans></sun-ejb-jar>
6.10. Test the application
The application has been successfully deployed and is ready for testing. You can use the following URL to access the application's home page: http: //
Figure 1 shows the snapshot of the home page.
Figure 1. Web Access tracker Homepage
You can click the Web Access Info link provided in the navigation bar on the left to view the Web Access Report. The report is displayed in Figure 2.
Figure 2. Web Access Report
VII. Conclusion
In this article, we explored the message passing functions of JMS and glassfish. Without a doubt, JMS has won extensive industry support and become a powerful enterprise message delivery solution. The application cases explained in this article really demonstrate the advantages of using message passing solution to solve real-time problems in JMS.