Develop message-driven Bean
JavaJava messageservice)
Java Message Service (JMS) is a developer-neutral API used to access enterprise message systems. The Enterprise message system can assist application software in message interaction over the network.
The JMS programming process is very simple. In summary, application a sends a message to a certain destination of the Message Server, and then the Message Server forwards the message to application B. Because application a and application B do not have a direct code connection, the implementation of both is even better.
Messages in JMS
The center of the message passing system is the message. A Message consists of three parts:
Header, property, and body ).
Messages are of the following types, all of which are derived from the message interface.
Streammessage: a message that contains a Java primitive Value Stream. The filling and reading operations are performed in order.
Mapmessage: a message that contains a group of name-value pairs. The order of entries is not defined.
Textmessage: a message that contains a Java string (for example, an XML message ).
Objectmessage: a message that contains serialized Java objects.
Bytesmessage: a message that contains continuous byte streams.
Message transmission model
JMS supports two message transmission models: point-to-point (PTP) and publish/subscribe (pub/Sub ). The two message passing models are very similar, but there are the following differences:
The PTP message transmission model specifies that a message can only be transmitted to one receiver. It is represented by javax. JMS. queue.
The pub/sub message passing model allows one message to be transmitted to multiple receivers. Represented by javax. JMS. Topic
Both models are implemented by extending the public base class. For example, javax. JMS. queue and javax. JMS. Topic are both extended from the javax. JMS. Destination class.
Point-to-Point PTP message transmission model
Whoever listens first will receive it first.
Publish/subscribe message transmission model
Configure the target address
Before starting JMS programming, We need to configure the destination address (destination) for the message to arrive, because only the destination address exists, we can send the message to this address. As each application server has different configuration methods for the target address, the following uses JBoss as an example to configure a target address of the queue type.
<? XML version = "1.0" encoding = "UTF-8"?>
<Server>
<Mbeancode = "org. JBoss. MQ. server. JMX. queue"
Name = "JBoss. MQ. Destination: service = queue, name =Foshanshop">
<Attributename = "jndiname"> queue/foshanshop </attribute>
<Dependsoptional-Attribute-name = "destinationmanager"> JBoss. MQ: service = destinationmanager </depends>
</Mbean>
</Server>
JBoss uses an XML file to configure the queue address. The file name format must comply with *-service. xml
<Attribute name = "jndiname"> the attribute specifies the global JNDI name of the target address. If you do not specify the jndiname attribute, JBoss will generate a default global JNDI for you. Its name consists of "queue" + "/" + target address name. In addition, before any queue or topic is deployed, the application server must first deploy the destination manager mbean. Therefore, we declare this dependency through the <depends> node.
Bold custom settings, black do not need to be changed.
Steps:
Create a new hqu-service.xml on the desktop copy the XML code above to modify the bold Section:
<? Xmlversion ="1.0"Encoding =UTF-8"?>
<Server>
<Mbeancode ="Org. JBoss. MQ. server. JMX. queue"
Name ="JBoss. MQ. Destination: service = queue, name = hququeue">
<Attributename ="Jndiname"> Queue/hququeue </attribute>
<Dependsoptional-Attribute-name ="Destinationmanager">
JBoss. MQ: service = destinationmanager </depends>
</Mbean>
</Server>
Release: copy to the JBoss Server \ Default \ deploy and release it. You can view the release information on the console.
You can see http: // localhost: 8080/JMX-console/on the JBoss Management page/
Name = hququeue, service = queue under JBoss. MQ. Destination
After the target address is set up, we can send messages.
Send messages in Java class
To send a message, follow these steps:
(1) Get a JNDI initialization context (context)
Initialcontextctx = new initialcontext ();
(2) query a connection factory named queueconnectionfactory Based on the context. The connection factory is provided by JMS and does not need to be created by ourselves. Each Vendor binds a global JNDI for it and we can obtain it through its Global JNDI;
Queueconnectionfactoryfactory = (queueconnectionfactory)
CTX. Lookup ("queueconnectionfactory ");
(3) Get a connection queueconnection from the connection Factory
Conn = factory. createqueueconnection ();
(4) Establish a session through a connection );
Session = conn. createqueuesession (false, queuesession. auto_acknowledge );
This code indicates creating a session that does not require transactions and can automatically confirm that the message has been received.
(5) Find the target address:
Sample Code: destinationdestination = (destination) CTX. Lookup ("queue/hququeue ");
(6) Create messageproducer (both queuesender and topicpublisher are extended from the messageproducer Interface) based on the session and target address)
Sample Code:
Messageproducer producer = session. createproducer (destination );
Textmessage MSG = session. createtextmessage ("Hello, this is my first message-driven Bean ");
Producer. Send (MSG );
Steps:
Create a message-driven bean project, create a javaproject: messagedrivenbean, add the JAR file required by the EJB, and create a Java class: queuesender under CN. hqu. app for sending queue.
Package CN. hqu. APP; import javax. JMS. destination; import javax. JMS. messageproducer; import javax. JMS. queueconnection; import javax. JMS. queueconnectionfactory; import javax. JMS. queuesession; import javax. naming. initialcontext; public class queuesender {public static void main (string [] ARGs) {try {// 1. initialize a JNDI context object initialcontext CTX = new initialcontext (); // 2. query a connection factory named queueconnectionfactoryqueueconn Based on the context. Ectionfactory factory = (queueconnectionfactory) CTX. Lookup ("queueconnectionfactory"); // 3. You can create a queue to connect to queueconnection through the connection factory. Queueconnection conn = factory. createqueueconnection (); // 4. create a session queuesession session = conn by connecting to the target address. createqueuesession (false, queuesession. auto_acknowledge); // 5. find the destination address destination Destination = (destination) CTX. lookup ("queue/hququeue"); // 6. the message sender messageproducer producer = session is obtained. createproducer (destination); // with this sender, we can send the message: producer. send (Session. createtextmessage ("Hello, Su Zhida"); Session. close (); Conn. close ();} catch (exception e) {e. printstacktrace ();}}}
Write the sending code inside the method,
1. First initialize a JNDI context object:
Copy the jdni. Properties of the previous project to SRC, In the mian class of queuesender
Try{
InitialcontextCTX=NewInitialcontext ();
}Catch(Namingexception e ){
E. printstacktrace ();
}
.
2. query a connection factory named queueconnectionfactory Based on the context.
Find the connection factory of the queue type,
QueueconnectionfactoryFactory= (Queueconnectionfactory) CTX. Lookup ("queueconnectionfactory ");
3. You can create a queue to connect to queueconnection through the connection factory.
QueueconnectionConn= Factory. createqueueconnection ();
4. Create a session to the destination address through a connection: the first parameter specifies whether a transaction is required, and the second parameter specifies the message confirmation mode.
QueuesessionSession= Conn. createqueuesession (False, Queuesession.Auto_acknowledge);
5. Find the target address:
DestinationDestination= (Destination) CTX. Lookup ("queue/hququeue ");
6. Get the message sender
MessageproducerProducer= Session. createproducer (destination );
With this sender, we can send the message:
Producer. Send (session. createtextmessage ("Hello, suzhida "));
The caller sends a message to the target address and runs main. After the message is sent, write the message receiver.
Message-driven bean for receiving messages
You can receive messages in the form of Java classes. Here, message-driven Bean (Message Driven bean) is used to receive messages, because message-driven Bean (MDB) is a component specially designed to process message requests. Like stateless Session Bean, it also uses the instance pool technology. containers can use a certain number of bean instances.Concurrent processing of hundreds of JMS messages. Because MDB can process a large number of concurrent messages, it is very suitable for some message gateway products. If a service is executed for a long time and the execution result does not need to be reported to the user in real time, MDB is also suitable for use. If the order is successful, send an email or text message to the user.
An MDB usually implements the messagelistener interface, which defines the onmessage () method. Bean uses it to process received JMS messages.
Package javax. JMS;
Public interface messagelistener {
Public void onmessage (message );
}
When the container detects that a message arrives at the target address waiting for the bean, the container calls the onmessage () method to pass the message as a parameter to the MDB. MDB decides how to process the message in onmessage. You can use annotations to specify which Destination Address (destination) The MDB listens ). When MDB is deployed, the container reads the configuration information.
Steps:
Create a message-driven Bean: messagedrivenbean implements messagelistener under CN. hqu. Message.
When the container detects that a message has arrived at the target address listened to by this JavaBean, it will help us obtain this message and send it to onmessage.
Annotations can be used to specify the type of the message-driven bean listening target address and the JNDI name of the target address.
@ Messagedriven (activationconfig =
{
@ Activationconfigproperty (propertyname = "destinationtype ",
Propertyvalue = "javax. JMS. queue "),
@ Activationconfigproperty (propertyname = "destination ",
Propertyvalue = "queue/hququeu "),
@ Activationconfigproperty (propertyname = "acknowledgemode ",
Propertyvalue = "auto-acknowledge ")
})
Public classMessagedrivenbeanImplementsMessagelistener {
From the target address of the queue type, find the destination address bound by the JNDI queue/hququeu. When a message is received, the message confirmation mode is automatic confirmation. Acknowledgemode is the default mode, so this can be removed.
Process received messages in the onmessage Method
Public voidOnmessage (Message MSG ){
Textmessage message = (textmessage) MSG;
Try{
System.Out. Println (message. gettext ());
}Catch(Jmsexception e ){
E. printstacktrace ();
}
}
For packaging and deployment. Copy the ant of the previous project and change the name of the configuration file build. XML
Messagedrivenbean.
Run deploy to publish the message-driven bean to JBoss. Print on the console
16:07:57, 999 info [jmxkernel1_action] installing mbean: JBoss. J2EE: jar = Messa
Gedrivenbean. jar, name = messagedrivenbean, service = ejb3with dependencies:
16:07:58, 015 info [ejbcontainer] started EJB: CN. hqu. Message. messagedrivenbean
Ejbname: messagedrivenbean
16:07:58, 039 info [ejb3deployer] deployed: file:/F:/Java/jboss-4.2.2.GA/Server/
Default/deploy/messagedrivenbean. Jar
16:07:58, 060 info [stdout] Hello, suzhida
Received messages.
JMS allows the sender and receiver to be offline at the same time. There is no code association between the two, achieving good decoupling.
Code: http://pan.baidu.com/s/1bn2DgPT
The sending of the queue type is complete.
Topic sending and receiving.
Step 1 configure the destination address, type not queue type, is topic type, add a topic configuration in the configuration file hqu-service.xml
<Mbean code = "org. JBoss. MQ. server. JMX. Topic"
Name = "JBoss. MQ. Destination: service = topic, name = hqutopic">
<Attribute name = "jndiname"> topic/hqutopic </attribute>
<Depends optional-Attribute-name = "destinationmanager">
JBoss. MQ: service = destinationmanager </depends>
</Mbean>
After configuration, publish it to JBoss (copy it in ).
The topicsender class is created under CN. hqu. app to publish messages of the topic type. The JNDI name can be seen in the released console.
Package CN. hqu. APP; import javax. JMS. destination; import javax. JMS. messageproducer; import javax. JMS. topicconnection; import javax. JMS. topicconnectionfactory; import javax. JMS. topicsession; import javax. naming. initialcontext; public class topicsender {/*** @ Param ARGs */public static void main (string [] ARGs) {try {// 1. initialize a JNDI context object initialcontext CTX = new initialcontext (); // 2. query a connection factory named queueconnec Based on the context. Tionfactorytopicconnectionfactory factory = (topicconnectionfactory) CTX. Lookup ("topicconnectionfactory"); // 3. You can create a queue to connect to queueconnection through the connection factory. Topicconnection conn = factory. createtopicconnection (); // 4. create a session topicsession session = conn through a connection. createtopicsession (false, topicsession. auto_acknowledge); // 5. find the destination address destination Destination = (destination) CTX. lookup ("Topic/hqutopic"); // 6. the message sender messageproducer producer = session is obtained. createproducer (destination); // with this sender, we can send the message: producer. send (Session. createtextmessage ("Hello, Su Zhida"); Session. close (); Conn. close ();} catch (exception e) {e. printstacktrace ();}}}
Run main.
The receiver of the development message. Because it will be received by multiple parties, two message-driven beans are created.
Create a new receivebean to implement messagelistener under CN. hqu. Message.
package cn.hqu.message;import javax.ejb.ActivationConfigProperty;import javax.ejb.MessageDriven;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.MessageListener;import javax.jms.TextMessage;@MessageDriven(activationConfig ={ @ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Topic"), @ActivationConfigProperty(propertyName="destination", propertyValue="topic/hquTopic")})public class ReceiveBean implements MessageListener {@Overridepublic void onMessage(Message msg) {TextMessage message = (TextMessage) msg;try {System.out.println(this.getClass()+message.getText());} catch (JMSException e) {e.printStackTrace();}}}
Another message-driven Bean: receiveotherbean
package cn.hqu.message;import javax.ejb.ActivationConfigProperty;import javax.ejb.MessageDriven;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.MessageListener;import javax.jms.TextMessage;@MessageDriven(activationConfig ={ @ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Topic"), @ActivationConfigProperty(propertyName="destination", propertyValue="topic/hquTopic") })public class ReceiveOtherBean implements MessageListener {@Overridepublic void onMessage(Message msg) {TextMessage message = (TextMessage) msg;try {System.out.println(this.getClass()+message.getText());} catch (JMSException e) {e.printStackTrace();}}}
Release and run ant deploy
The topic message just sent is not displayed after the publishing is complete. Because for a topic message, if the receiver does not listen to the message of this topic type at the time, the message cannot be obtained, although we deploy it to JBoss now, because it didn't listen to the target address of the topic at the time, he could not get the message.
Now we can run the topic sending command to view the messages sent by multiple receivers on the console.
Code: http://pan.baidu.com/s/1nthubNF