Upload
vance-wilson
View
95
Download
3
Embed Size (px)
DESCRIPTION
Message-Driven Bean(MDB). Goals. Be able to produce messages from the EJB server Be able to consume messages within the EJB server Be able to define timers within EJB server. Objectives. EJB JMS Producers EJB JMS Consumers (Message Driven Beans; MDBs) Asynchronous Methods EJB Timers. 3. - PowerPoint PPT Presentation
Citation preview
EnterpriseJava
Message-Driven Bean(MDB)
1
EnterpriseJavaGoals
• Be able to produce messages from the EJB server• Be able to consume messages within the EJB server• Be able to define timers within EJB server
v131202 Asynchronous EJB 2
EnterpriseJavaObjectives
• EJB JMS Producers• EJB JMS Consumers (Message Driven Beans; MDBs)• Asynchronous Methods• EJB Timers
v131202 Asynchronous EJB 3 3
EnterpriseJavaEJB JMS Producers
• Obtain Resources– ConnectionFactory– Destination
• Create Session– integrate with JTA transaction
• Publish Message
v131202 Asynchronous EJB 4 4
EnterpriseJavaObtaining a ConnectionFactory
• Using annotations@Statelesspublic class SellerEJB ... { @Resource(mappedName=“java:/JmsXA") private ConnectionFactory connFactory;
–mappedName points to global JNDI name
–benefits• concise & simple
–drawbacks• mixes deployment concepts with Java code
v131202 Asynchronous EJB 5 5
EnterpriseJavaObtaining a ConnectionFactory (cont.)
• Using ejb-jar.xml<ejb-name>SellerEJB</ejb-name> <resource-ref>
<res-ref-name>jms/ConnectionFactory</res-ref-name> <res-type>javax.jms.ConnectionFactory</res-type> <mapped-name>java:/JmsXA</mapped-name> <injection-target> <injection-target-class>
ejava.examples.asyncmarket.ejb.SellerEJB</injection-target-class><injection-target-name>
connFactory</injection-target-name>
</injection-target></resource-ref>...
–mappedName moved away from code to DD–factory injected into EJB–ejb-jar.xml is no longer vendor/deployment-neutral
v131202 Asynchronous EJB 6 6
EnterpriseJavaObtaining a ConnectionFactory (cont.)
• Using jboss-ejb3.xml <session> <ejb-name>SellerEJB</ejb-name> <resource-ref> <res-ref-name>jms/ConnectionFactory</res-ref-name> <jndi-name>java:/JmsXA</jndi-name> </resource-ref> </session>
–mappedName is now removed• replaced with vendor/deployment specific reference
–Required 3 files to complete
v131202 Asynchronous EJB 7v111128 Asynchronous EJB 7
EnterpriseJavaObtaining a Destination
• Using annotations@Statelesspublic class SellerEJB implements SellerLocal, SellerRemote { ... @Resource(mappedName="java:/topic/ejava/examples/asyncMarket/topic1", type=Topic.class)
private Destination sellTopic;
–mappedName points to global JNDI entry–benefits
• concise and simple–drawbacks
• mixes deployment properties with implementation
v131202 Asynchronous EJB 8v111128 Asynchronous EJB 8
EnterpriseJavaObtaining a Destination (cont.)
• Using ejb-jar.xml<resource-env-ref>
<resource-env-ref-name>jms/sellTopic</resource-env-ref-name> <resource-env-ref-type>javax.jms.Topic</resource-env-ref-type> <mapped-name>topic/ejava/examples/asyncMarket/topic</mapped-name> <injection-target> <injection-target-class> ejava.examples.asyncmarket.ejb.SellerEJB </injection-target-class> <injection-target-name>sellTopic</injection-target-name>
</injection-target></resource-env-ref>
–mappedName moved away from Java and to DD–note resource-env-ref used for Destinations
v131202 Asynchronous EJB 9v111128 Asynchronous EJB 9
EnterpriseJava
@TransactionAttribute(TransactionAttributeType.REQUIRED)public long sellProduct(String sellerId, AuctionItem item)
throws MarketException { Connection connection = null; Session session = null; try { connection = connFactory.createConnection(); session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE); ... } catch (JMSException ex) { log.error("error publishing sell", ex); ctx.setRollbackOnly(); throw new EJBException("error publishing sell:" + ex); } finally { try { if (session != null) { session.close(); } if (connection != null) { connection.close(); } } catch (JMSException ex) { log.error("unable to close resources", ex); } } }
Getting a Session
v131202 Asynchronous EJB 1010
EnterpriseJava
Person seller = sellerDAO.getPersonByUserId(sellerId); seller.getItems().add(item); item.setOwner(seller); auctionItemDAO.createItem(item); publishForSale(session, item); return item.getId();
Integrating JMS into the Transaction
v131202 Asynchronous EJB 1111
EnterpriseJava
protected void publishForSale(Session session, AuctionItem item) throws JMSException { MessageProducer producer = null; try { producer = session.createProducer(sellTopic); MapMessage message = session.createMapMessage(); message.setJMSType("forSale"); message.setLong("id", item.getId()); message.setString("name", item.getName()); message.setString("seller", item.getOwner().getUserId()); message.setLong("startDate", item.getStartDate().getTime()); message.setLong("endDate", item.getEndDate().getTime()); message.setDouble("minBid", item.getMinBid()); message.setDouble("bids", item.getBids().size()); message.setDouble("highestBid", (item.getHighestBid() == null ? 0.00 : item.getHighestBid().getAmount())); producer.send(message); } finally { if (producer != null) { producer.close(); } } }
Publishing the Message
v131202 Asynchronous EJB 1212
EnterpriseJava
• “Message Driven Bean”• Introduced in EJB 2.0 to support JMS providers• Extended in EJB 2.1 to support non-JMS message
providers– using the Java EE Connector API
• commonly called JCA• EJB 3.0 added @Annotation support for configuration• Java EE Providers
– must support a JMS provider– must support external providers through JCA
• Session and Entity Beans cannot be a MessageListener– can poll for messages with MessageConsumer.receive()– can be wrapped by an MDB to be called asynchronously
EJB JMS Consumers; MDBs
v131202 Asynchronous EJB 1313
EnterpriseJava
• Destination Type• Destination• Selector• Message Acknowledgement• ...
MessageDriven Bean Configuration
v131202 Asynchronous EJB 1414
EnterpriseJava
• Using annotations@MessageDriven(name="BuyerMDB", activationConfig={ @ActivationConfigProperty( propertyName="destinationType", propertyValue="javax.jms.Topic"), @ActivationConfigProperty( propertyName="destination", propertyValue="topic/ejava/.../topic1"), @ActivationConfigProperty( propertyName="messageSelector", propertyValue=
"JMSType in ('forSale', 'saleUpdate')"), @ActivationConfigProperty( propertyName="acknowledgeMode", propertyValue="Auto-acknowledge") })public class BuyerMDB implements MessageListener {
MDB Configuration
v131202 Asynchronous EJB 1515
EnterpriseJava
• Using ejb-jar.xml<message-driven> <ejb-name>BuyerMDB</ejb-name> <ejb-class>ejava.examples.asyncmarket.ejb.BuyerMDB</ejb-class> <message-destination-type>
javax.jms.Topic</message-destination-type>
<activation-config> <activation-config-property>
<activation-config-property-name> ...</activation-config-property-name>
<activation-config-property-value> ...</activation-config-property-value>
</activation-config-property> </activation-config>
MDB Configuration (cont.)
v131202 Asynchronous EJB 1616
EnterpriseJava
• Using jboss.xml<message-driven> <ejb-name>BuyerMDB</ejb-name> <destination-jndi-name> topic/ejava/examples/asyncMarket/topic1 </destination-jndi-name>
MDB Configuration (cont.)
Asynchronous EJB 17v111128 17
EnterpriseJava
18
MDB Structure@MessageDriven(name="BuyerMDB", activationConfig={ ... })public class BuyerMDB implements MessageListener { @PostConstruct public void init() { ... }
public void onMessage(Message message) { try { log.debug("onMessage:" + message.getJMSMessageID()); MapMessage auctionMsg = (MapMessage)message; long itemId = auctionMsg.getLong("id"); processAuctionItem(itemId); } catch (Exception ex) { log.error("error processing message", ex); } }
EnterpriseJava
• SUPPORTED– message receipt/acknowledgement integrated with
overall transaction• NOT_SUPPORTED
– message receipt/acknowledgement independent of transactions within processing
MDB and Transactions
Asynchronous EJB 19v111128 19
EnterpriseJava
• Scenario– Task(s) may take considerable time to complete– Client need not wait for them to complete
• @javax.ejb.Asynchronous – Return control to the client before EJB is invoked– Any session bean business method may be made
@Asynchronous* (*see Serialization note below)
• null return type– Client and issued task fully decoupled from one another
• java.util.concurrent.Future return type– Allows task and client to coordinate a future return value– Client returns instance of javax.ejb.AsyncResult– Not Serializable (i.e., cannot use directly with RMI client)
Asynchronous Methods
20
EnterpriseJava
@Statelesspublic class AuctionMgmtEJB implements AuctionMgmtRemote, AuctionMgmtLocal { private @EJB AuctionMgmtActionEJB actions;
public void workSync(int count, long delay) { DateFormat df = new SimpleDateFormat("HH:mm:ss.SSS"); long startTime = System.currentTimeMillis(); for (int i=0; i<count; i++) { log.info(String.format("%s issuing sync request, delay=%d", df.format(new Date()), delay)); Date date= actions.doWorkSync(delay); log.info(String.format("sync waitTime=%d msecs", System.currentTimeMillis()-startTime)); } long syncTime = System.currentTimeMillis() - startTime;
log.info(String.format("workSync time=%d msecs", syncTime)); }
Synchronous Example: Client EJB
21
EnterpriseJava
@Statelesspublic class AuctionMgmtActionEJB { public Date doWorkSync(long delay) { DateFormat df = new SimpleDateFormat("HH:mm:ss.SSS"); log.debug(String.format("sync method %d starting %d delay at %s", Thread.currentThread().getId(), delay, df.format(new Date()))); try { Thread.sleep(delay); } catch (Exception ex) { ... } Date now = new Date(); log.debug(String.format("sync method %d completed %d delay at %s", Thread.currentThread().getId(), delay, df.format(now))); return now;}
Synchronous Example: Helper EJB
22
EnterpriseJava
11:06:44,624 INFO [AuctionMgmtEJB:306] 11:06:44.612 issuing sync request, delay=300011:06:44,626 DEBUG [AuctionMgmtActionEJB:24] sync method 163 starting 3000 delay at 11:06:44.62611:06:47,628 DEBUG [AuctionMgmtActionEJB:30] sync method 163 completed 3000 delay at 11:06:47,630 INFO [AuctionMgmtEJB:309] sync waitTime=3018 msecs11:06:47,631 INFO [AuctionMgmtEJB:306] 11:06:47.631 issuing sync request, delay=300011:06:47,634 DEBUG [AuctionMgmtActionEJB:24] sync method 163 starting 3000 delay at 11:06:47.63411:06:50,636 DEBUG [AuctionMgmtActionEJB:30] sync method 163 completed 3000 delay at 11:06:50,637 INFO [AuctionMgmtEJB:309] sync waitTime=6025 msecs11:06:50,637 INFO [AuctionMgmtEJB:306] 11:06:50.637 issuing sync request, delay=300011:06:50,638 DEBUG [AuctionMgmtActionEJB:24] sync method 163 starting 3000 delay at 11:06:50.63811:06:53,640 DEBUG [AuctionMgmtActionEJB:30] sync method 163 completed 3000 delay at 11:06:53.64011:06:53,641 INFO [AuctionMgmtEJB:309] sync waitTime=9029 msecs
11:06:53,642 INFO [AuctionMgmtEJB:312] workSync time=9030 msecs
Synchronous Example: Results
23
EnterpriseJava
@Statelesspublic class AuctionMgmtEJB implements AuctionMgmtRemote, AuctionMgmtLocal { public void workAsync(int count, long delay) { DateFormat df = new SimpleDateFormat("HH:mm:ss.SSS"); long startTime = System.currentTimeMillis(); List<Future<Date>> results = new ArrayList<Future<Date>>(); for (int i=0; i<count; i++) { log.info(String.format("%s issuing async request, delay=%d", df.format(new Date()), delay)); Future<Date> date = actions.doWorkAsync(delay); results.add(date); log.info(String.format("async waitTime=%d msecs", System.currentTimeMillis()-startTime)); } for (Future<Date> f: results) { log.info(String.format("%s getting async response", df.format(new Date()))); try { Date date = f.get(); } catch (Exception ex) { throw new EJBException("unexpected error in future.get():"+ex);} log.info(String.format("%s got async response", df.format(new Date()))); } long asyncTime = System.currentTimeMillis() - startTime; log.info(String.format("workAsync time=%d msecs", asyncTime));}
Asynchronous Example: Client EJB
24
EnterpriseJava
@Statelesspublic class AuctionMgmtActionEJB { @javax.ejb.Asynchronous public java.util.concurrent.Future<Date> doWorkAsync(long delay) { DateFormat df = new SimpleDateFormat("HH:mm:ss.SSS"); log.debug(String.format("async method %d starting %d delay at %s", Thread.currentThread().getId(), delay, df.format(new Date()))); try { Thread.sleep(delay); } catch (Exception ex) { ... } Date now = new Date(); log.debug(String.format("async method %d completed %d delay at %s", Thread.currentThread().getId(), delay, df.format(now)));
return new javax.ejb.AsyncResult<Date>(now); }
Asynchronous Example: Helper EJB
25
EnterpriseJava
11:06:53,650 INFO [AuctionMgmtEJB:325] 11:06:53.650 issuing async request, delay=300011:06:53,658 INFO [AuctionMgmtEJB:328] async waitTime=8 msecs11:06:53,659 INFO [AuctionMgmtEJB:325] 11:06:53.659 issuing async request, delay=300011:06:53,659 DEBUG [AuctionMgmtActionEJB:41] async method 166 starting 3000 delay at 11:06:53.65911:06:53,668 DEBUG [AuctionMgmtActionEJB:41] async method 167 starting 3000 delay at 11:06:53.66811:06:53,668 INFO [AuctionMgmtEJB:328] async waitTime=18 msecs11:06:53,669 INFO [AuctionMgmtEJB:325] 11:06:53.669 issuing async request, delay=300011:06:53,670 INFO [AuctionMgmtEJB:328] async waitTime=20 msecs11:06:53,670 DEBUG [AuctionMgmtActionEJB:41] async method 168 starting 3000 delay at 11:06:53.67011:06:53,671 INFO [AuctionMgmtEJB:331] 11:06:53.671 getting async response11:06:56,667 DEBUG [AuctionMgmtActionEJB:47] async method 166 completed 3000 delay at 11:06:56,669 DEBUG [AuctionMgmtActionEJB:47] async method 167 completed 3000 delay at 11:06:56,669 INFO [AuctionMgmtEJB:339] 11:06:56.669 got async response11:06:56,670 INFO [AuctionMgmtEJB:331] 11:06:56.670 getting async response11:06:56,671 INFO [AuctionMgmtEJB:339] 11:06:56.671 got async response11:06:56,672 DEBUG [AuctionMgmtActionEJB:47] async method 168 completed 3000 delay at 11:06:56,673 INFO [AuctionMgmtEJB:331] 11:06:56.672 getting async response11:06:56,673 INFO [AuctionMgmtEJB:339] 11:06:56.673 got async response
11:06:56,674 INFO [AuctionMgmtEJB:342] workAsync time=3024 msecs
Asynchronous Example: Results
26
EnterpriseJava
• Performs similar role of job schedulers– “cron”
• Two types– Single-action
• createTimer(Date expiration, Serializable info)– fires once at or after a specific time in the future
• createTimer(long duration, Serializable info)– fires once after a specific delay period
– Interval-timer• createTimer(Date intialExpiration, long intervalDuration, Serializable info)
– continually fires every intervalDuration after the initialExpiration time
• createTimer(long initialDuration, long intervalDuration, Serializable info)
– continually fires every intervalDuration after the initialDuration delay
EJB Timers
v131202 Asynchronous EJB 2727
EnterpriseJava
• Original EJB Timer Service part of EJB 2.1• EJB 3.0 added annotation-based extensions that
eliminated inheritance-based solution requirements• EJB 3.1 provided an overhaul of the overall service
– Added declarative scheduling• @javax.ejb.ScheduleExpression• @javax.ejb.Schedule
EJB Timers
28
EnterpriseJava
@Schedule(second="*/10", minute ="*", hour="*", dayOfMonth="*", month="*", year="*”, persistent=false)
public void execute(Timer timer) { log.info("timer fired:" + timer); try { checkAuction(); } catch (Exception ex) { log.error("error checking auction", ex); } }
Declarative Calendar Timer
29
EnterpriseJava
ScheduleExpression schedule = new ScheduleExpression(); schedule.second("*/10"); schedule.minute("*"); schedule.hour("*"); schedule.dayOfMonth("*"); schedule.month("*"); schedule.year("*"); auctionMgmt.initTimers(schedule);
public void initTimers(ScheduleExpression schedule) { cancelTimers(); log.debug("initializing timers, schedule="+schedule); timerService.createCalendarTimer(schedule);}
@Timeoutpublic void execute(Timer timer) { log.info("timer fired:" + timer); try { checkAuction(); } catch (Exception ex) { log.error("error checking auction", ex); }}
Programmatic Calendar Timer
30
EnterpriseJava
auctionMgmt.initTimers(10*1000);
public void initTimers(long delay) { cancelTimers(); log.debug("initializing timers, checkItemInterval="+delay); timerService.createTimer(0,delay, "checkAuctionTimer");}
@Timeoutpublic void execute(Timer timer) { log.info("timer fired:" + timer); try { checkAuction(); } catch (Exception ex) { log.error("error checking auction", ex); }}
Programmatic Interval Timer
31
EnterpriseJava
32
EJB Timers• Accessing TimerService
– Using Annotations@Resource private TimerService timerService;
• Getting TimerstimerService.getTimers()
• Cancelling Timersfor (Timer timer : (Collection<Timer>)timerService.getTimers()) {
timer.cancel();}
• Timers– associated with the EJB that created them– are automatically integrated into JTA transaction
EnterpriseJava
33
EJB Timer Callbacks• Using annotations
public class AuctionMgmtEJB ...@Timeoutpublic void execute(Timer timer) { try { checkAuction(); } catch (Exception ex) { log.error("error checking auction", ex); }}
• Using interfacespublic class AuctionMgmtEJB implements TimedObject, ...
public void ejbTimeout(Timer timer) { ... }}
EnterpriseJava
public interface javax.ejb.TimerService{ javax.ejb.Timer createTimer(long, java.io.Serializable) throws ...; javax.ejb.Timer createSingleActionTimer(long, javax.ejb.TimerConfig)
throws ...; javax.ejb.Timer createTimer(long, long, java.io.Serializable) throws ...; javax.ejb.Timer createIntervalTimer(long, long, javax.ejb.TimerConfig)
throws ...; javax.ejb.Timer createTimer(java.util.Date, java.io.Serializable) throws ...; javax.ejb.Timer createSingleActionTimer(java.util.Date, javax.ejb.TimerConfig)
throws ...; javax.ejb.Timer createTimer(java.util.Date, long, java.io.Serializable)
throws ...; javax.ejb.Timer createIntervalTimer(java.util.Date, long,javax.ejb.TimerConfig)
throws ...; javax.ejb.Timer createCalendarTimer(javax.ejb.ScheduleExpression) throws ...; javax.ejb.Timer createCalendarTimer(javax.ejb.ScheduleExpression, javax.ejb.TimerConfig) throws ...; java.util.Collection getTimers() throws ...;}
javax.ejb.TimerService
34
EnterpriseJava
• EJB JMS Publishers– integrates into Session and MDB processing
• EJB JMS Subscriber– implemented using MDB– MDBs support more than JMS using JCA
• Asynchronous Methods• EJB Timers
– schedule re-activation of Session Bean– Single-action and interval
Summary
v131202 Asynchronous EJB 3535
EnterpriseJava
36
References
• Java Messaging Service API– http://java.sun.com/javaee/5/docs/api/javax/jms/package-
summary.html• “Enterprise JavaBeans 3.0, 5th Edition”; Burke &
Monsen-Haefel; ISBN 0-596-00978-X; O'Reilly