Download presentation
Presentation is loading. Please wait.
1
Message-Driven Bean(MDB)
2
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 v131202 Asynchronous EJB
3
Objectives EJB JMS Producers
EJB JMS Consumers (Message Driven Beans; MDBs) Asynchronous Methods EJB Timers v131202 Asynchronous EJB 3
4
EJB JMS Producers Obtain Resources Create Session Publish Message
ConnectionFactory Destination Create Session integrate with JTA transaction Publish Message v131202 Asynchronous EJB 4
5
Obtaining a ConnectionFactory
Using annotations @Stateless public 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
6
Obtaining 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
7
Obtaining 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 v111128 Asynchronous EJB 7
8
Obtaining a Destination
Using annotations @Stateless public 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 v111128 Asynchronous EJB 8
9
Obtaining 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 v111128 Asynchronous EJB 9
10
Getting a Session v131202 Asynchronous EJB 10
@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 { if (session != null) { session.close(); } if (connection != null) { connection.close(); } } catch (JMSException ex) { log.error("unable to close resources", ex); v131202 Asynchronous EJB 10
11
Integrating JMS into the Transaction
Person seller = sellerDAO.getPersonByUserId(sellerId); seller.getItems().add(item); item.setOwner(seller); auctionItemDAO.createItem(item); publishForSale(session, item); return item.getId(); v131202 Asynchronous EJB 11
12
Publishing the Message
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(); } v131202 Asynchronous EJB 12
13
EJB JMS Consumers; MDBs
“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 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 v131202 Asynchronous EJB 13
14
MessageDriven Bean Configuration
Destination Type Destination Selector Message Acknowledgement ... v131202 Asynchronous EJB 14
15
MDB Configuration Using annotations v131202 Asynchronous EJB
@MessageDriven(name="BuyerMDB", activationConfig={ @ActivationConfigProperty( propertyName="destinationType", propertyValue="javax.jms.Topic"), propertyName="destination", propertyValue="topic/ejava/.../topic1"), propertyName="messageSelector", propertyValue= "JMSType in ('forSale', 'saleUpdate')"), propertyName="acknowledgeMode", propertyValue="Auto-acknowledge") }) public class BuyerMDB implements MessageListener { v131202 Asynchronous EJB 15
16
MDB Configuration (cont.)
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> v131202 Asynchronous EJB 16
17
MDB Configuration (cont.)
Using jboss.xml <message-driven> <ejb-name>BuyerMDB</ejb-name> <destination-jndi-name> topic/ejava/examples/asyncMarket/topic1 </destination-jndi-name> Asynchronous EJB v111128 17
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);
19
MDB and Transactions SUPPORTED NOT_SUPPORTED
message receipt/acknowledgement integrated with overall transaction NOT_SUPPORTED message receipt/acknowledgement independent of transactions within processing Asynchronous EJB v111128 19
20
Asynchronous Methods Scenario @javax.ejb.Asynchronous null return type
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 (*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)
21
Synchronous Example: Client EJB
@Stateless public class AuctionMgmtEJB implements AuctionMgmtRemote, AuctionMgmtLocal { 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));
22
Synchronous Example: Helper EJB
@Stateless public 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; }
23
Synchronous Example: Results
11:06:44,624 INFO [AuctionMgmtEJB:306] 11:06: issuing sync request, delay= :06:44,626 DEBUG [AuctionMgmtActionEJB:24] sync method 163 starting 3000 delay at 11:06: :06:47,628 DEBUG [AuctionMgmtActionEJB:30] sync method 163 completed 3000 delay at 11:06:47,630 INFO [AuctionMgmtEJB:309] sync waitTime=3018 msecs 11:06:47,631 INFO [AuctionMgmtEJB:306] 11:06: issuing sync request, delay= :06:47,634 DEBUG [AuctionMgmtActionEJB:24] sync method 163 starting 3000 delay at 11:06: :06:50,636 DEBUG [AuctionMgmtActionEJB:30] sync method 163 completed 3000 delay at 11:06:50,637 INFO [AuctionMgmtEJB:309] sync waitTime=6025 msecs 11:06:50,637 INFO [AuctionMgmtEJB:306] 11:06: issuing sync request, delay= :06:50,638 DEBUG [AuctionMgmtActionEJB:24] sync method 163 starting 3000 delay at 11:06: :06:53,640 DEBUG [AuctionMgmtActionEJB:30] sync method 163 completed 3000 delay at 11:06: :06:53,641 INFO [AuctionMgmtEJB:309] sync waitTime=9029 msecs 11:06:53,642 INFO [AuctionMgmtEJB:312] workSync time=9030 msecs
24
Asynchronous Example: Client EJB
@Stateless public 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));
25
Asynchronous Example: Helper EJB
@Stateless public class AuctionMgmtActionEJB 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); }
26
Asynchronous Example: Results
11:06:53,650 INFO [AuctionMgmtEJB:325] 11:06: issuing async request, delay= :06:53,658 INFO [AuctionMgmtEJB:328] async waitTime=8 msecs 11:06:53,659 INFO [AuctionMgmtEJB:325] 11:06: issuing async request, delay= :06:53,659 DEBUG [AuctionMgmtActionEJB:41] async method 166 starting 3000 delay at 11:06: :06:53,668 DEBUG [AuctionMgmtActionEJB:41] async method 167 starting 3000 delay at 11:06: :06:53,668 INFO [AuctionMgmtEJB:328] async waitTime=18 msecs 11:06:53,669 INFO [AuctionMgmtEJB:325] 11:06: issuing async request, delay= :06:53,670 INFO [AuctionMgmtEJB:328] async waitTime=20 msecs 11:06:53,670 DEBUG [AuctionMgmtActionEJB:41] async method 168 starting 3000 delay at 11:06: :06:53,671 INFO [AuctionMgmtEJB:331] 11:06: getting async response 11: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: got async response 11:06:56,670 INFO [AuctionMgmtEJB:331] 11:06: getting async response 11:06:56,671 INFO [AuctionMgmtEJB:339] 11:06: got async response 11:06:56,672 DEBUG [AuctionMgmtActionEJB:47] async method 168 completed 3000 delay at 11:06:56,673 INFO [AuctionMgmtEJB:331] 11:06: getting async response 11:06:56,673 INFO [AuctionMgmtEJB:339] 11:06: got async response 11:06:56,674 INFO [AuctionMgmtEJB:342] workAsync time=3024 msecs
27
EJB Timers Performs similar role of job schedulers Two types v131202
“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 v131202 Asynchronous EJB 27
28
EJB Timers 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
29
Declarative Calendar Timer
@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);
30
Programmatic Calendar Timer
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); public void execute(Timer timer) { log.info("timer fired:" + timer); try { checkAuction(); catch (Exception ex) { log.error("error checking auction", ex);
31
Programmatic Interval Timer
auctionMgmt.initTimers(10*1000); public void initTimers(long delay) { cancelTimers(); log.debug("initializing timers, checkItemInterval="+delay); timerService.createTimer(0,delay, "checkAuctionTimer"); } @Timeout public void execute(Timer timer) { log.info("timer fired:" + timer); try { checkAuction(); catch (Exception ex) { log.error("error checking auction", ex);
32
EJB Timers Accessing TimerService Getting Timers Cancelling Timers
Using Annotations @Resource private TimerService timerService; Getting Timers timerService.getTimers() Cancelling Timers for (Timer timer : (Collection<Timer>)timerService.getTimers()) { timer.cancel(); } Timers associated with the EJB that created them are automatically integrated into JTA transaction
33
EJB Timer Callbacks Using annotations Using interfaces
public class AuctionMgmtEJB ... @Timeout public void execute(Timer timer) { try { checkAuction(); } catch (Exception ex) { log.error("error checking auction", ex); Using interfaces public class AuctionMgmtEJB implements TimedObject, ... public void ejbTimeout(Timer timer) { ...
34
javax.ejb.TimerService
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) javax.ejb.Timer createTimer(java.util.Date, java.io.Serializable) throws ...; javax.ejb.Timer createSingleActionTimer(java.util.Date, javax.ejb.TimerConfig) javax.ejb.Timer createTimer(java.util.Date, long, java.io.Serializable) javax.ejb.Timer createIntervalTimer(java.util.Date, long,javax.ejb.TimerConfig) javax.ejb.Timer createCalendarTimer(javax.ejb.ScheduleExpression) throws ...; javax.ejb.Timer createCalendarTimer(javax.ejb.ScheduleExpression, javax.ejb.TimerConfig) throws ...; java.util.Collection getTimers() throws ...; }
35
Summary EJB JMS Publishers EJB JMS Subscriber Asynchronous Methods
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 v131202 Asynchronous EJB 35
36
References Java Messaging Service API
“Enterprise JavaBeans 3.0, 5th Edition”; Burke & Monsen-Haefel; ISBN X; O'Reilly
Similar presentations
© 2025 SlidePlayer.com Inc.
All rights reserved.