(Original) Message-driven bean of ejb3 -- MDB

Source: Internet
Author: User

EJB: the business logic component. in J2EE, the business logic is basically implemented by the EJB component and the WebService interface is released externally (of course, using open-source frameworks that comply with JAX-WS specifications can be done without EJB ).

Therefore, although EJB was born for a long time, it is not out of date, but many people are discouraged from it, which has a lot to do with its own reasons.

The difference in JNDI between EJB and different containers leads to various troubles.

It is particularly prominent in ejb1 and ejb2. I am ashamed that it took a month for helloworld OF THE FIRST EJB a few years ago!

However, because there is no actual demand, and there is not much effort to study, so that a lot of knowledge is abandoned, and now it is re-picked. A person has to learn too much in his life.

MDB ---- message-driven bean is used as a JMS consumer.

MDB is a change from stateless Session Bean. Therefore, MDB and stateless Session Bean are similar in usage. For example, they do not save the call status of the client, they can be shared by multiple clients.

But what is the difference between stateless sssion bean and MDB?

Stateless Session Bean:

1)A service interface is provided. The client needs to call the stateless Session Bean in synchronous mode.

2)When the client calls the service method of the stateless Session Bean, the client is blocked before the service method of the stateless Session Bean is returned.

MDB:

1)MDB cannot be called directly by the client. It is only a message listener.

2)MDB adopts asynchronous communication, and the message producer cannot directly call MDB. The message producer only sends a message to a specified destination. How long does it take to process when MDB is triggered and how it is triggered, the message producer does not need to care about it.

At the same time, whether MDB is a business logic component or a control component can only be human and cloud.

It is believed that the business component is followed because MDB is developed from the stateless session bean, and the stateless Session Bean is set up by the business logic.

It is regarded as a control component because MDB is essentially a message listener and starts to act with the message:

For this reason, the categories vary according to my personal opinion.

 

Below is a simple example to illustrate MDB:

Before that, make the following preparations:

Register a database connection in the container or JBoss. Here I use the oracle.

First, define an MDB interface:

@Remotepublic interface Student {    void add(String name,String gender,int age)throws Exception;}

Then a class implements this interface:

@ Stateless (name = "studentbean") public class studentbean implements student {// use the dependency injection data source @ Resource (name = "oracle") Private datasource Ds; public void add (string name, string gender, int age) throws exception {connection conn = NULL; preparedstatement pstmt = NULL; try {// obtain the database connection conn = DS through the data source. getconnection (); // use preparedstatement to execute the SQL statement pstmt = Conn. preparestatement ("select * from EMP where id =? "); Pstmt. setint (1, age); resultset rs = pstmt.exe cutequery (); If (RS. next () {system. out. println (RS. getstring ("name") ;}} finally {pstmt. close (); Conn. close ();}}}

The class dB is called directly here, which is not used in actual development. JPA is generally used. This is just an exercise.

So far, we have a basic interface, implementation class, that is, the implementation class that actually processes the business already exists, so there is currently no listener, that is to say, when listening to messages to trigger the actual service class, write a listener class. The main function of this class is to trigger the student implementation class when a message arrives:

// Specify the type of the message that the MDB listens to @ messagedriven (activationconfig = {@ activationconfigproperty (propertyname = "destinationtype", propertyvalue = "javax. JMS. queue "), @ activationconfigproperty (propertyname =" acknowledgemode ", propertyvalue =" auto-acknowledge "), // specify the JNDI binding name of the message monitored by MDB @ activationconfigproperty (propertyname = "destination", propertyvalue = "messagequeue ")} // specify the JNDI name of the message listened by MDB, mappedname = "messagequeue") // directly implement the messagelistener interface public class studentmesagelistener implements messagelistener {@ EJB (name = "studentbean ") private student; Public void onmessage (Message MSG) {system. out. println ("entity listening class received message:"); try {If (MSG instanceof mapmessage) {mapmessage map = (mapmessage) MSG; string name = map. getstring ("name"); string gender = map. getstring ("gender"); int age = map. getint ("Age"); student. add (name, gender, age) ;}} catch (exception e) {e. printstacktrace ();}}}

Make a client to call:

/*** Send a message to the message-driven bean * add data to the database through instance * @ author root **/public class sendmessagestudent {public void sendmessage () throws jmsexception, namingexception {// defines the JNDI final string connection_factory_jndi = "weblogic. JMS. connectionfactory "; // get cotext context CTX = getinitialcontext () required by the JNDI service; // obtain the connection factory connectionfactory connfactory = (connectionfactory) CTX through the JNDI search. lookup (connection_factory_jndi); // connection factory creates connection conn = connfactory. createconnection (); // obtain the destination DEST = (destination) CTX. lookup ("messagequeue"); // create a JMS session = Conn. createsession (false/* not a transactional session */, session. auto_acknowledge); // create a message producer messageproducer sender = session in the JMS session. createproducer (DEST); // sets the message transmission mode produced by the message producer. The effective time is sender. setdeliverymode (deliverymode. persistent); sender. settimetolive (20000); // creates a text message mapmessage MSG = session through a JMS session. createmapmessage (); // sets the message content MSG. setstring ("name", "BFC"); MSG. setstring ("gender", "BFC"); MSG. setint ("Age", 2); system. out. println ("start sending -----"); sender. send (MSG); system. out. println ("sent -----"); // closes the resource session. close (); Conn. close ();} private context getinitialcontext () {context CTX = NULL; properties props = new properties (); props. setproperty (context. initial_context_factory, "weblogic. JNDI. wlinitialcontextfactory "); props. setproperty (context. provider_url, "T3: // localhost: 7001"); try {CTX = new initialcontext (props);} catch (namingexception e) {e. printstacktrace ();} return CTX;} public static void main (string ARGs []) {sendmessagestudent MP = new sendmessagestudent (); try {MP. sendmessage ();} catch (jmsexception e) {e. printstacktrace ();} catch (namingexception e) {e. printstacktrace ();}}}

This seems to have been completed, but after the deployment and test, there is a problem. The error is as follows:

Caused by: javax.transaction.xa.XAException: JDBC driver does not support XA, hence cannot be a participant in two-phase commit. To force this participation, set the GlobalTransactionsProtocol attribute to LoggingLastResource (recommended) or EmulateTwoPhaseCommit for the Data Source = Oracle    at weblogic.jdbc.wrapper.JTSXAResourceImpl.prepare(JTSXAResourceImpl.java:83)    at weblogic.transaction.internal.XAServerResourceInfo.prepare(XAServerResourceInfo.java:1342)    at weblogic.transaction.internal.XAServerResourceInfo.prepare(XAServerResourceInfo.java:513)    at weblogic.transaction.internal.ServerSCInfo$1.run(Unknown Source)    ... 3 more.> 

You cannot perform two commit operations and have not started two transactions. Baidu Googles a bit and rarely gets an answer. You can see JDBC driver does not support XA, hence cannot be a participant

Seriously suspect that it is a driver problem, because I have registered MySql in the container for Oracle.

Replace the Oracle driver:

At the same time, set the transaction processing of another database, MySQL,:

 

After the modification, the problem is solved, the EJB is deployed, and the program is run. The result is correct:

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.