360 likes | 407 Views
Asynchronous EJB. 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. v111128.
E N D
Asynchronous EJB Asynchronous EJB
Asynchronous EJB 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
Asynchronous EJB Objectives • EJB JMS Producers • EJB JMS Consumers (Message Driven Beans; MDBs) • Asynchronous Methods • EJB Timers v111128 Asynchronous EJB 3
Asynchronous EJB EJB JMS Producers • Obtain Resources • ConnectionFactory • Destination • Create Session • integrate with JTA transaction • Publish Message v111128 Asynchronous EJB 4
Asynchronous EJB Obtaining a ConnectionFactory • Using annotations @Stateless public class SellerEJB ... { @Resource(lookup=“java:/JmsXA") private ConnectionFactoryconnFactory; • Lookup points to global JNDI name • benefits • concise & simple • drawbacks • mixes deployment concepts with Java code v111128 Asynchronous EJB 5
Asynchronous EJB 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> <lookup-name>java:/JmsXA</lookup-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> ... • Lookup moved away from code to DD • factory injected into EJB • ejb-jar.xml is no longer vendor/deployment-neutral v111128 Asynchronous EJB 6
Asynchronous EJB 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> • Lookup is now removed • replaced with vendor/deployment specific reference • Required 3 files to complete v111128 Asynchronous EJB 7
Asynchronous EJB Obtaining a Destination • Using annotations @Stateless public class SellerEJBimplements SellerLocal, SellerRemote { ... @Resource(lookup="java:/topic/ejava/examples/asyncMarket/topic1", type=Topic.class) private Destination sellTopic; • Lookup points to global JNDI entry • benefits • concise and simple • drawbacks • mixes deployment properties with implementation v111128 Asynchronous EJB 8
Asynchronous EJB 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> <lookup-name>topic/ejava/examples/asyncMarket/topic</lookup-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 v111128 Asynchronous EJB 9
Asynchronous EJB Getting a Session @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); } } } v111128 Asynchronous EJB 10
Asynchronous EJB 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(); v111128 Asynchronous EJB 11
Asynchronous EJB 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(); } } } v111128 Asynchronous EJB 12
Asynchronous EJB 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 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 v111128 Asynchronous EJB 13
Asynchronous EJB MessageDriven Bean Configuration • Destination Type • Destination • Selector • Message Acknowledgement • ... v111128 Asynchronous EJB 14
Asynchronous EJB MDB Configuration • 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 { v111128 Asynchronous EJB 15
Asynchronous EJB 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> v111128 Asynchronous EJB 16
Asynchronous EJB MDB Configuration (cont.) • Using jboss.xml <message-driven> <ejb-name>BuyerMDB</ejb-name> <destination-jndi-name> topic/ejava/examples/asyncMarket/topic1 </destination-jndi-name> v111128 Asynchronous EJB 17
Asynchronous EJB 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); } }
Asynchronous EJB MDB and Transactions • SUPPORTED • message receipt/acknowledgement integrated with overall transaction • NOT_SUPPORTED • message receipt/acknowledgement independent of transactions within processing v111128 Asynchronous EJB 19
Asynchronous EJB Asynchronous Methods • 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 EJB Synchronous Example: Client EJB @Stateless public 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)); }
Asynchronous EJB 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; }
Asynchronous EJB Synchronous Example: Results 11:06:44,624 INFO [AuctionMgmtEJB:306] 11:06:44.612 issuing sync request, delay=3000 11:06:44,626 DEBUG [AuctionMgmtActionEJB:24] sync method 163 starting 3000 delay at 11:06:44.626 11: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:47.631 issuing sync request, delay=3000 11:06:47,634 DEBUG [AuctionMgmtActionEJB:24] sync method 163 starting 3000 delay at 11:06:47.634 11: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:50.637 issuing sync request, delay=3000 11:06:50,638 DEBUG [AuctionMgmtActionEJB:24] sync method 163 starting 3000 delay at 11:06:50.638 11:06:53,640 DEBUG [AuctionMgmtActionEJB:30] sync method 163 completed 3000 delay at 11:06:53.640 11:06:53,641 INFO [AuctionMgmtEJB:309] sync waitTime=9029 msecs 11:06:53,642 INFO [AuctionMgmtEJB:312] workSync time=9030 msecs
Asynchronous EJB 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)); }
Asynchronous EJB Asynchronous Example: Helper EJB @Stateless public 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 EJB Asynchronous Example: Results 11:06:53,650 INFO [AuctionMgmtEJB:325] 11:06:53.650 issuing async request, delay=3000 11:06:53,658 INFO [AuctionMgmtEJB:328] async waitTime=8 msecs 11:06:53,659 INFO [AuctionMgmtEJB:325] 11:06:53.659 issuing async request, delay=3000 11:06:53,659 DEBUG [AuctionMgmtActionEJB:41] async method 166 starting 3000 delay at 11:06:53.659 11:06:53,668 DEBUG [AuctionMgmtActionEJB:41] async method 167 starting 3000 delay at 11:06:53.668 11:06:53,668 INFO [AuctionMgmtEJB:328] async waitTime=18 msecs 11:06:53,669 INFO [AuctionMgmtEJB:325] 11:06:53.669 issuing async request, delay=3000 11: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:53.670 11:06:53,671 INFO [AuctionMgmtEJB:331] 11:06:53.671 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:56.669 got async response 11:06:56,670 INFO [AuctionMgmtEJB:331] 11:06:56.670 getting async response 11:06:56,671 INFO [AuctionMgmtEJB:339] 11:06:56.671 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:56.672 getting async response 11: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 EJB EJB Timers • 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 v111128 Asynchronous EJB 27
Asynchronous EJB 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
Asynchronous EJB 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); } }
Asynchronous EJB 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); } @Timeout public void execute(Timer timer) { log.info("timer fired:" + timer); try { checkAuction(); } catch (Exception ex) { log.error("error checking auction", ex); } }
Asynchronous EJB 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); } }
Asynchronous EJB EJB Timers • Accessing TimerService • 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
Asynchronous EJB EJB Timer Callbacks • Using annotations 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) { ... } }
Asynchronous EJB 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) 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 ...; }
Asynchronous EJB Summary • 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 v111128 Asynchronous EJB 35
Asynchronous EJB 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