Enterprise Java MessageDriven BeanMDB 1 Goals Enterprise Java
Enterprise Java Message-Driven Bean(MDB) 1
Goals Enterprise Java • 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 v 131202 Asynchronous EJB 2
Objectives • • Enterprise Java EJB JMS Producers EJB JMS Consumers (Message Driven Beans; MDBs) Asynchronous Methods EJB Timers v 131202 Asynchronous EJB 33
EJB JMS Producers Enterprise Java • Obtain Resources – Connection. Factory – Destination • Create Session – integrate with JTA transaction • Publish Message v 131202 Asynchronous EJB 44
Obtaining a Connection. Factory Enterprise Java • Using annotations @Stateless public class Seller. EJB. . . { @Resource(mapped. Name=“java: /Jms. XA") private Connection. Factory conn. Factory; –mapped. Name points to global JNDI name –benefits • concise & simple –drawbacks • mixes deployment concepts with Java code v 131202 Asynchronous EJB 55
Obtaining a Connection. Factory (cont. ) Enterprise Java • Using ejb-jar. xml <ejb-name>Seller. EJB</ejb-name> <resource-ref> <res-ref-name>jms/Connection. Factory</res-ref-name> <res-type>javax. jms. Connection. Factory</res-type> <mapped-name>java: /Jms. XA</mapped-name> <injection-target-class> ejava. examples. asyncmarket. ejb. Seller. EJB </injection-target-class> <injection-target-name> conn. Factory </injection-target-name> </injection-target> </resource-ref>. . . –mapped. Name moved away from code to DD –factory injected into EJB –ejb-jar. xml is no longer vendor/deployment-neutral v 131202 Asynchronous EJB 66
Obtaining a Connection. Factory (cont. ) Enterprise Java • Using jboss-ejb 3. xml <session> <ejb-name>Seller. EJB</ejb-name> <resource-ref> <res-ref-name>jms/Connection. Factory</res-ref-name> <jndi-name>java: /Jms. XA</jndi-name> </resource-ref> </session> –mapped. Name is now removed • replaced with vendor/deployment specific reference –Required 3 files to complete v 131202 v 111128 Asynchronous EJB 77
Obtaining a Destination Enterprise Java • Using annotations @Stateless public class Seller. EJB implements Seller. Local, Seller. Remote {. . . @Resource(mapped. Name="java: /topic/ejava/examples/async. Market/topic 1", type=Topic. class) private Destination sell. Topic; –mapped. Name points to global JNDI entry –benefits • concise and simple –drawbacks • mixes deployment properties with implementation v 131202 v 111128 Asynchronous EJB 88
Obtaining a Destination (cont. ) Enterprise Java • Using ejb-jar. xml <resource-env-ref> <resource-env-ref-name>jms/sell. Topic</resource-env-ref-name> <resource-env-ref-type>javax. jms. Topic</resource-env-ref-type> <mapped-name>topic/ejava/examples/async. Market/topic</mapped-name> <injection-target-class> ejava. examples. asyncmarket. ejb. Seller. EJB </injection-target-class> <injection-target-name>sell. Topic</injection-target-name> </injection-target> </resource-env-ref> –mapped. Name moved away from Java and to DD –note resource-env-ref used for Destinations v 131202 v 111128 Asynchronous EJB 99
Getting a Session Enterprise Java @Transaction. Attribute(Transaction. Attribute. Type. REQUIRED) public long sell. Product(String seller. Id, Auction. Item item) throws Market. Exception { Connection connection = null; Session session = null; try { connection = conn. Factory. create. Connection(); session = connection. create. Session(false, Session. AUTO_ACKNOWLEDGE); . . . } catch (JMSException ex) { log. error("error publishing sell", ex); ctx. set. Rollback. Only(); 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); } } } v 131202 Asynchronous EJB 1010
Integrating JMS into the Transaction Enterprise Java Person seller = seller. DAO. get. Person. By. User. Id(seller. Id); seller. get. Items(). add(item); item. set. Owner(seller); auction. Item. DAO. create. Item(item); publish. For. Sale(session, item); return item. get. Id(); v 131202 Asynchronous EJB 1111
Publishing the Message Enterprise Java protected void publish. For. Sale(Session session, Auction. Item item) throws JMSException { Message. Producer producer = null; try { producer = session. create. Producer(sell. Topic); Map. Message message = session. create. Map. Message(); message. set. JMSType("for. Sale"); message. set. Long("id", item. get. Id()); message. set. String("name", item. get. Name()); message. set. String("seller", item. get. Owner(). get. User. Id()); message. set. Long("start. Date", item. get. Start. Date(). get. Time()); message. set. Long("end. Date", item. get. End. Date(). get. Time()); message. set. Double("min. Bid", item. get. Min. Bid()); message. set. Double("bids", item. get. Bids(). size()); message. set. Double("highest. Bid", (item. get. Highest. Bid() == null ? 0. 00 : item. get. Highest. Bid(). get. Amount())); producer. send(message); } finally { if (producer != null) { producer. close(); } } } v 131202 Asynchronous EJB 1212
EJB JMS Consumers; MDBs Enterprise Java • “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 Message. Listener – can poll for messages with Message. Consumer. receive() – can be wrapped by an MDB to be called asynchronously v 131202 Asynchronous EJB 1313
Message. Driven Bean Configuration • • • Enterprise Java Destination Type Destination Selector Message Acknowledgement. . . v 131202 Asynchronous EJB 1414
MDB Configuration Enterprise Java • Using annotations @Message. Driven(name="Buyer. MDB", activation. Config={ @Activation. Config. Property( property. Name="destination. Type", property. Value="javax. jms. Topic"), @Activation. Config. Property( property. Name="destination", property. Value="topic/ejava/. . . /topic 1"), @Activation. Config. Property( property. Name="message. Selector", property. Value= "JMSType in ('for. Sale', 'sale. Update')"), @Activation. Config. Property( property. Name="acknowledge. Mode", property. Value="Auto-acknowledge") }) public class Buyer. MDB implements Message. Listener { v 131202 Asynchronous EJB 1515
MDB Configuration (cont. ) Enterprise Java • Using ejb-jar. xml <message-driven> <ejb-name>Buyer. MDB</ejb-name> <ejb-class>ejava. examples. asyncmarket. ejb. Buyer. MDB</ejb-class> <message-destination-type> javax. jms. Topic </message-destination-type> <activation-config-property> <activation-config-property-name>. . . </activation-config-property-name> <activation-config-property-value>. . . </activation-config-property-value> </activation-config-property> </activation-config> v 131202 Asynchronous EJB 1616
MDB Configuration (cont. ) Enterprise Java • Using jboss. xml <message-driven> <ejb-name>Buyer. MDB</ejb-name> <destination-jndi-name> topic/ejava/examples/async. Market/topic 1 </destination-jndi-name> v 111128 Asynchronous EJB 1717
MDB Structure Enterprise Java @Message. Driven(name="Buyer. MDB", activation. Config={. . . }) public class Buyer. MDB implements Message. Listener { @Post. Construct public void init() {. . . } public void on. Message(Message message) { try { log. debug("on. Message: " + message. get. JMSMessage. ID()); Map. Message auction. Msg = (Map. Message)message; long item. Id = auction. Msg. get. Long("id"); process. Auction. Item(item. Id); } catch (Exception ex) { log. error("error processing message", ex); } } 18
MDB and Transactions Enterprise Java • SUPPORTED – message receipt/acknowledgement integrated with overall transaction • NOT_SUPPORTED – message receipt/acknowledgement independent of transactions within processing v 111128 Asynchronous EJB 1919
Asynchronous Methods Enterprise Java • 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. Async. Result – Not Serializable (i. e. , cannot use directly with RMI client) 20
Synchronous Example: Client EJB Enterprise Java @Stateless public class Auction. Mgmt. EJB implements Auction. Mgmt. Remote, Auction. Mgmt. Local { private @EJB Auction. Mgmt. Action. EJB actions; public void work. Sync(int count, long delay) { Date. Format df = new Simple. Date. Format("HH: mm: ss. SSS"); long start. Time = System. current. Time. Millis(); 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. do. Work. Sync(delay); log. info(String. format("sync wait. Time=%d msecs", System. current. Time. Millis()-start. Time)); } long sync. Time = System. current. Time. Millis() - start. Time; log. info(String. format("work. Sync time=%d msecs", sync. Time)); } 21
Synchronous Example: Helper EJB Enterprise Java @Stateless public class Auction. Mgmt. Action. EJB { public Date do. Work. Sync(long delay) { Date. Format df = new Simple. Date. Format("HH: mm: ss. SSS"); log. debug(String. format("sync method %d starting %d delay at %s", Thread. current. Thread(). get. Id(), 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. current. Thread(). get. Id(), delay, df. format(now))); return now; } 22
Synchronous Example: Results Enterprise Java 11: 06: 44, 624 INFO [Auction. Mgmt. EJB: 306] 11: 06: 44. 612 issuing sync request, delay=3000 11: 06: 44, 626 DEBUG [Auction. Mgmt. Action. EJB: 24] sync method 163 starting 3000 delay at 11: 06: 44. 626 11: 06: 47, 628 DEBUG [Auction. Mgmt. Action. EJB: 30] sync method 163 completed 3000 delay at 11: 06: 47, 630 INFO [Auction. Mgmt. EJB: 309] sync wait. Time=3018 msecs 11: 06: 47, 631 INFO [Auction. Mgmt. EJB: 306] 11: 06: 47. 631 issuing sync request, delay=3000 11: 06: 47, 634 DEBUG [Auction. Mgmt. Action. EJB: 24] sync method 163 starting 3000 delay at 11: 06: 47. 634 11: 06: 50, 636 DEBUG [Auction. Mgmt. Action. EJB: 30] sync method 163 completed 3000 delay at 11: 06: 50, 637 INFO [Auction. Mgmt. EJB: 309] sync wait. Time=6025 msecs 11: 06: 50, 637 INFO [Auction. Mgmt. EJB: 306] 11: 06: 50. 637 issuing sync request, delay=3000 11: 06: 50, 638 DEBUG [Auction. Mgmt. Action. EJB: 24] sync method 163 starting 3000 delay at 11: 06: 50. 638 11: 06: 53, 640 DEBUG [Auction. Mgmt. Action. EJB: 30] sync method 163 completed 3000 delay at 11: 06: 53. 640 11: 06: 53, 641 INFO [Auction. Mgmt. EJB: 309] sync wait. Time=9029 msecs 11: 06: 53, 642 INFO [Auction. Mgmt. EJB: 312] work. Sync time=9030 msecs 23
Asynchronous Example: Client EJB Enterprise Java @Stateless public class Auction. Mgmt. EJB implements Auction. Mgmt. Remote, Auction. Mgmt. Local { public void work. Async(int count, long delay) { Date. Format df = new Simple. Date. Format("HH: mm: ss. SSS"); long start. Time = System. current. Time. Millis(); List<Future<Date>> results = new Array. List<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. do. Work. Async(delay); results. add(date); log. info(String. format("async wait. Time=%d msecs", System. current. Time. Millis()-start. Time)); } 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 async. Time = System. current. Time. Millis() - start. Time; log. info(String. format("work. Async time=%d msecs", async. Time)); } 24
Enterprise Java Asynchronous Example: Helper EJB @Stateless public class Auction. Mgmt. Action. EJB { @javax. ejb. Asynchronous public java. util. concurrent. Future<Date> do. Work. Async(long delay) { Date. Format df = new Simple. Date. Format("HH: mm: ss. SSS"); log. debug(String. format("async method %d starting %d delay at %s", Thread. current. Thread(). get. Id(), 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. current. Thread(). get. Id(), delay, df. format(now))); return new javax. ejb. Async. Result<Date>(now) ; } 25
Asynchronous Example: Results Enterprise Java 11: 06: 53, 650 INFO [Auction. Mgmt. EJB: 325] 11: 06: 53. 650 issuing async request, delay=3000 11: 06: 53, 658 INFO [Auction. Mgmt. EJB: 328] async wait. Time=8 msecs 11: 06: 53, 659 INFO [Auction. Mgmt. EJB: 325] 11: 06: 53. 659 issuing async request, delay=3000 11: 06: 53, 659 DEBUG [Auction. Mgmt. Action. EJB: 41] async method 166 starting 3000 delay at 11: 06: 53. 659 11: 06: 53, 668 DEBUG [Auction. Mgmt. Action. EJB: 41] async method 167 starting 3000 delay at 11: 06: 53. 668 11: 06: 53, 668 INFO [Auction. Mgmt. EJB: 328] async wait. Time=18 msecs 11: 06: 53, 669 INFO [Auction. Mgmt. EJB: 325] 11: 06: 53. 669 issuing async request, delay=3000 11: 06: 53, 670 INFO [Auction. Mgmt. EJB: 328] async wait. Time=20 msecs 11: 06: 53, 670 DEBUG [Auction. Mgmt. Action. EJB: 41] async method 168 starting 3000 delay at 11: 06: 53. 670 11: 06: 53, 671 INFO [Auction. Mgmt. EJB: 331] 11: 06: 53. 671 getting async response 11: 06: 56, 667 DEBUG [Auction. Mgmt. Action. EJB: 47] async method 166 completed 3000 delay at 11: 06: 56, 669 DEBUG [Auction. Mgmt. Action. EJB: 47] async method 167 completed 3000 delay at 11: 06: 56, 669 INFO [Auction. Mgmt. EJB: 339] 11: 06: 56. 669 got async response 11: 06: 56, 670 INFO [Auction. Mgmt. EJB: 331] 11: 06: 56. 670 getting async response 11: 06: 56, 671 INFO [Auction. Mgmt. EJB: 339] 11: 06: 56. 671 got async response 11: 06: 56, 672 DEBUG [Auction. Mgmt. Action. EJB: 47] async method 168 completed 3000 delay at 11: 06: 56, 673 INFO [Auction. Mgmt. EJB: 331] 11: 06: 56. 672 getting async response 11: 06: 56, 673 INFO [Auction. Mgmt. EJB: 339] 11: 06: 56. 673 got async response 11: 06: 56, 674 INFO [Auction. Mgmt. EJB: 342] work. Async time=3024 msecs 26
EJB Timers Enterprise Java • Performs similar role of job schedulers – “cron” • Two types – Single-action • create. Timer(Date expiration, Serializable info) – fires once at or after a specific time in the future • create. Timer(long duration, Serializable info) – fires once after a specific delay period – Interval-timer • create. Timer(Date intial. Expiration, long interval. Duration, Serializable info) – continually fires every interval. Duration after the initial. Expiration time • create. Timer(long initial. Duration, long interval. Duration, Serializable info) – continually fires every interval. Duration after the initial. Duration delay v 131202 Asynchronous EJB 2727
EJB Timers Enterprise Java • 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. Schedule. Expression • @javax. ejb. Schedule 28
Declarative Calendar Timer Enterprise Java @Schedule(second="*/10", minute ="*", hour="*", day. Of. Month="*", month="*", year="*”, persistent=false) public void execute(Timer timer) { log. info("timer fired: " + timer); try { check. Auction(); } catch (Exception ex) { log. error("error checking auction", ex); } } 29
Programmatic Calendar Timer Enterprise Java Schedule. Expression schedule = new Schedule. Expression(); schedule. second("*/10"); schedule. minute("*"); schedule. hour("*"); schedule. day. Of. Month("*"); schedule. month("*"); schedule. year("*"); auction. Mgmt. init. Timers(schedule); public void init. Timers(Schedule. Expression schedule ) { cancel. Timers(); log. debug("initializing timers, schedule="+schedule); timer. Service. create. Calendar. Timer(schedule); } @Timeout public void execute(Timer timer) { log. info("timer fired: " + timer); try { check. Auction(); } catch (Exception ex) { log. error("error checking auction", ex); } } 30
Programmatic Interval Timer Enterprise Java auction. Mgmt. init. Timers(10*1000); public void init. Timers(long delay) { cancel. Timers(); log. debug("initializing timers, check. Item. Interval="+delay); timer. Service. create. Timer(0, delay, "check. Auction. Timer"); } @Timeout public void execute(Timer timer) { log. info("timer fired: " + timer); try { check. Auction(); } catch (Exception ex) { log. error("error checking auction", ex); } } 31
EJB Timers Enterprise Java • Accessing Timer. Service – Using Annotations @Resource private Timer. Service timer. Service; • Getting Timers timer. Service. get. Timers() • Cancelling Timers for (Timer timer : (Collection<Timer>)timer. Service. get. Timers()) { timer. cancel(); } • Timers – associated with the EJB that created them – are automatically integrated into JTA transaction 32
EJB Timer Callbacks Enterprise Java • Using annotations public class Auction. Mgmt. EJB. . . @Timeout public void execute(Timer timer) { try { check. Auction(); } catch (Exception ex) { log. error("error checking auction", ex); } } • Using interfaces public class Auction. Mgmt. EJB implements Timed. Object, . . . public void ejb. Timeout(Timer timer) {. . . } } 33
javax. ejb. Timer. Service Enterprise Java public interface javax. ejb. Timer. Service{ javax. ejb. Timer create. Timer(long, java. io. Serializable) throws. . . ; javax. ejb. Timer create. Single. Action. Timer(long, javax. ejb. Timer. Config) throws. . . ; javax. ejb. Timer create. Timer(long, java. io. Serializable) throws. . . ; javax. ejb. Timer create. Interval. Timer(long, javax. ejb. Timer. Config) throws. . . ; javax. ejb. Timer create. Timer(java. util. Date, java. io. Serializable) throws. . . ; javax. ejb. Timer create. Single. Action. Timer(java. util. Date, javax. ejb. Timer. Config) throws. . . ; javax. ejb. Timer create. Timer(java. util. Date, long, java. io. Serializable) throws. . . ; javax. ejb. Timer create. Interval. Timer(java. util. Date, long, javax. ejb. Timer. Config) throws. . . ; javax. ejb. Timer create. Calendar. Timer(javax. ejb. Schedule. Expression, javax. ejb. Timer. Config) throws. . . ; java. util. Collection get. Timers() throws. . . ; } 34
Summary Enterprise Java • 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 v 131202 Asynchronous EJB 3535
References Enterprise Java • Java Messaging Service API – http: //java. sun. com/javaee/5/docs/api/javax/jms/packagesummary. html • “Enterprise Java. Beans 3. 0, 5 th Edition”; Burke & Monsen-Haefel; ISBN 0 -596 -00978 -X; O'Reilly 36
- Slides: 36