Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

36
Enterprise Java Asynchronous EJB v131202 Asynchronous EJB 1

Transcript of Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

Page 1: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

EnterpriseJava

Asynchronous EJB

v131202 Asynchronous EJB 1

Page 2: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

EnterpriseJavaObjectives

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

v131202 Asynchronous EJB 3v111128 Asynchronous EJB 3

Page 4: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

EnterpriseJavaEJB JMS Producers

• Obtain Resources– ConnectionFactory– Destination

• Create Session– integrate with JTA transaction

• Publish Message

v131202 Asynchronous EJB 4v111128 Asynchronous EJB 4

Page 5: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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 5v111128 Asynchronous EJB 5

Page 6: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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 6v111128 Asynchronous EJB 6

Page 7: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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 10v111128 Asynchronous EJB 10

Page 11: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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 11v111128 Asynchronous EJB 11

Page 12: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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 12v111128 Asynchronous EJB 12

Page 13: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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 13v111128 Asynchronous EJB 13

Page 14: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

EnterpriseJava

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

MessageDriven Bean Configuration

v131202 Asynchronous EJB 14v111128 Asynchronous EJB 14

Page 15: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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 15v111128 Asynchronous EJB 15

Page 16: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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 16v111128 Asynchronous EJB 16

Page 17: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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

v131202 Asynchronous EJB 17v111128 Asynchronous EJB 17

Page 18: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

EnterpriseJava

v131202 Asynchronous EJB 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: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

EnterpriseJava

• SUPPORTED– message receipt/acknowledgement integrated with

overall transaction• NOT_SUPPORTED

– message receipt/acknowledgement independent of transactions within processing

MDB and Transactions

v131202 Asynchronous EJB 19v111128 Asynchronous EJB 19

Page 20: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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

v131202 Asynchronous EJB 20

Page 21: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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

v131202 Asynchronous EJB 21

Page 22: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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

v131202 Asynchronous EJB 22

Page 23: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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

v131202 Asynchronous EJB 23

Page 24: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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

v131202 Asynchronous EJB 24

Page 25: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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

v131202 Asynchronous EJB 25

Page 26: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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

v131202 Asynchronous EJB 26

Page 27: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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 27v111128 Asynchronous EJB 27

Page 28: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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

v131202 Asynchronous EJB 28

Page 29: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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

v131202 Asynchronous EJB 29

Page 30: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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

v131202 Asynchronous EJB 30

Page 31: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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

v131202 Asynchronous EJB 31

Page 32: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

EnterpriseJava

v131202 Asynchronous EJB 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: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

EnterpriseJava

v131202 Asynchronous EJB 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: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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

v131202 Asynchronous EJB 34

Page 35: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

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 35v111128 Asynchronous EJB 35

Page 36: Enterprise Java Asynchronous EJB v131202Asynchronous EJB1.

EnterpriseJava

v131202 Asynchronous EJB 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