36
Enterprise Java Message-Driven Bean(MDB) 1

Message-Driven Bean(MDB)

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

Page 1: Message-Driven Bean(MDB)

EnterpriseJava

Message-Driven Bean(MDB)

1

Page 2: Message-Driven Bean(MDB)

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

Page 3: Message-Driven Bean(MDB)

EnterpriseJavaObjectives

• EJB JMS Producers• EJB JMS Consumers (Message Driven Beans; MDBs)• Asynchronous Methods• EJB Timers

v131202 Asynchronous EJB 3 3

Page 4: Message-Driven Bean(MDB)

EnterpriseJavaEJB JMS Producers

• Obtain Resources– ConnectionFactory– Destination

• Create Session– integrate with JTA transaction

• Publish Message

v131202 Asynchronous EJB 4 4

Page 5: Message-Driven Bean(MDB)

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

Page 6: Message-Driven Bean(MDB)

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

Page 7: Message-Driven Bean(MDB)

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

Page 8: Message-Driven Bean(MDB)

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

Page 9: Message-Driven Bean(MDB)

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

Page 10: Message-Driven Bean(MDB)

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

Page 11: Message-Driven Bean(MDB)

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

Page 12: Message-Driven Bean(MDB)

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

Page 13: Message-Driven Bean(MDB)

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

Page 14: Message-Driven Bean(MDB)

EnterpriseJava

• Destination Type• Destination• Selector• Message Acknowledgement• ...

MessageDriven Bean Configuration

v131202 Asynchronous EJB 1414

Page 15: Message-Driven Bean(MDB)

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

Page 16: Message-Driven Bean(MDB)

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

Page 17: Message-Driven Bean(MDB)

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

Page 18: Message-Driven Bean(MDB)

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); } }

Page 19: Message-Driven Bean(MDB)

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

Page 20: Message-Driven Bean(MDB)

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

Page 21: Message-Driven Bean(MDB)

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

Page 22: Message-Driven Bean(MDB)

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

Page 23: Message-Driven Bean(MDB)

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

Page 24: Message-Driven Bean(MDB)

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

Page 25: Message-Driven Bean(MDB)

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

Page 26: Message-Driven Bean(MDB)

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

Page 27: Message-Driven Bean(MDB)

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

Page 28: Message-Driven Bean(MDB)

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

Page 29: Message-Driven Bean(MDB)

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

Page 30: Message-Driven Bean(MDB)

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

Page 31: Message-Driven Bean(MDB)

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

Page 32: Message-Driven Bean(MDB)

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

Page 33: Message-Driven Bean(MDB)

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) { ... }}

Page 34: Message-Driven Bean(MDB)

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

Page 35: Message-Driven Bean(MDB)

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

Page 36: Message-Driven Bean(MDB)

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