G |
Message-Driven Beans |
|
Get |
Get |
Example: The Rock Survey, Take 3 |
After we completed Take 2 of the Rock Survey (see Example: The Rock Survey, Take 2 and Example: The Rock Survey, Take 2 (continued)), the application really does everything necessary to perform its task. But, for tutorial purposes, we're going to add a messaging layer. This can be a valid design under heavy loads and various other situations and design requirements. In addition, the example may give you some ideas about different approaches to processing in terms of timeliness, the client's view of the speed of an application, and loosely coupled operations.
Take 3 adds a message-driven bean (RockSurveyMDBean) and a modification of the existing session bean (RockSurvey2Bean). In the process, the application flow changes from a direct update of the datastore by the client application. Now the session bean sends a message, and the message-driven bean asynchronously manages the database update. Again, from the Web component's and end user's perspective there is no change except that the Done button operation returns more quickly.
All of the actual persistence code in the persist() method of RockSurvey2Bean, which in this version becomes RockSurvey3Bean, is removed and placed in RockSurveyMDBean. RockSurvey3Bean.persist() now gathers the data and sends a message containing an initialized RockSurveyData object (see Example: The Rock Survey, Take 1). Most of the relevant code is very similar to the code snippet in Sending and Receiving JMS Messages.
First, we declare the JMS-related instance variables:
// JMS variables for PTP
ObjectMessage om;
Queue q;
QueueConnection qc;
QueueConnectionFactory qcf;
QueueReceiver qReceiver;
QueueSender qSender;
QueueSession qSession;
TextMessage tm;
In persist(), if the QueueConnection hasn't yet been created, the necessary messaging objects are obtained:
if( qc == null)
{
// lookup the administered objects
ic = new InitialContext();
qcf = (QueueConnectionFactory)ic.lookup(
"java:comp/env/jms/QueueConnectionFactory" );
q = (Queue)ic.lookup(
"java:comp/env/jms/RockSurveyQueue" );
// create the necessary JMS objects
qc = qcf.createQueueConnection();
qSession = qc.createQueueSession(
false, Session.AUTO_ACKNOWLEDGE );
// create the sender
qSender = qSession.createSender( q );
} // end if qc is null
Notice that the QueueSession is created as nontransacted with automatic acknowledgement.
At this point, the program is ready to create message objects and send messages. Beginning and ending TextMessages are sent, with the send of the ObjectMessage (which contains the survey data) sandwiched in the middle. The ObjectMessage is loaded with rsd, a RockSurveyData object.
...
tm = qSession.createTextMessage(
"sending RockSurveyData to RockSurveyQueue." );
qSender.send( tm );
...
om = qSession.createObjectMessage( rsd );
qSender.send( om );
...
tm.setText( "RockSurveyData sent." );
qSender.send( tm );
...
That's it for the message sending portion. To conserve resources, in ejbPassivate() the QueueConnection is closed (this also closes the other related JMS objects) and the relevant instance variables are set to null. On termination, ejbRemove() invokes ejbPassivate() for the same purpose.
public void ejbPassivate()
{
if( qc != null)
{
try { qc.close(); }
catch (JMSException e) { /* can't do anything */ }
}
om = null;
q = null;
qc = null;
qcf = null;
qReceiver = null;
qSender = null;
qSession = null;
tm = null;
} // end ejbPassivate
|
|