Download Asynchronous EJB

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
Enterprise
Java
Asynchronous EJB
v131202
Asynchronous EJB
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
v131202
Asynchronous EJB
2
Objectives
•
•
•
•
Enterprise
Java
EJB JMS Producers
EJB JMS Consumers (Message Driven Beans; MDBs)
Asynchronous Methods
EJB Timers
v131202
v111128
Asynchronous
EJB
Asynchronous EJB
33
EJB JMS Producers
Enterprise
Java
• Obtain Resources
– ConnectionFactory
– Destination
• Create Session
– integrate with JTA transaction
• Publish Message
v131202
v111128
Asynchronous
EJB
Asynchronous EJB
44
Obtaining a ConnectionFactory
Enterprise
Java
• 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
v111128
Asynchronous
EJB
Asynchronous EJB
55
Enterprise
Java
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
v111128
Asynchronous
EJB
Asynchronous EJB
66
Enterprise
Java
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
v111128
Asynchronous
EJB
Asynchronous EJB
77
Obtaining a Destination
Enterprise
Java
• 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
v111128
Asynchronous
EJB
Asynchronous EJB
88
Obtaining a Destination (cont.)
Enterprise
Java
• 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
v111128
Asynchronous
EJB
Asynchronous EJB
99
Getting a Session
Enterprise
Java
@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);
}
}
}
v131202
v111128
Asynchronous
EJB
Asynchronous EJB
1010
Enterprise
Java
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
v111128
Asynchronous
EJB
Asynchronous EJB
1111
Publishing the Message
Enterprise
Java
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
v111128
Asynchronous
EJB
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 MessageListener
– can poll for messages with MessageConsumer.receive()
– can be wrapped by an MDB to be called asynchronously
v131202
v111128
Asynchronous
EJB
Asynchronous EJB
1313
MessageDriven Bean Configuration
•
•
•
•
•
Enterprise
Java
Destination Type
Destination
Selector
Message Acknowledgement
...
v131202
v111128
Asynchronous
EJB
Asynchronous EJB
1414
MDB Configuration
Enterprise
Java
• 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 {
v131202
v111128
Asynchronous
EJB
Asynchronous EJB
1515
MDB Configuration (cont.)
Enterprise
Java
• 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
v111128
Asynchronous
EJB
Asynchronous EJB
1616
MDB Configuration (cont.)
Enterprise
Java
• Using jboss.xml
<message-driven>
<ejb-name>BuyerMDB</ejb-name>
<destination-jndi-name>
topic/ejava/examples/asyncMarket/topic1
</destination-jndi-name>
v131202
v111128
Asynchronous
EJB
Asynchronous EJB
1717
MDB Structure
Enterprise
Java
@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);
}
}
v131202
Asynchronous EJB
18
MDB and Transactions
Enterprise
Java
• SUPPORTED
– message receipt/acknowledgement integrated with
overall transaction
• NOT_SUPPORTED
– message receipt/acknowledgement independent of
transactions within processing
v131202
v111128
Asynchronous
EJB
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.AsyncResult
– Not Serializable (i.e., cannot use directly with RMI client)
v131202
Asynchronous EJB
20
Synchronous Example: Client EJB
Enterprise
Java
@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));
}
v131202
Asynchronous EJB
21
Synchronous Example: Helper EJB
Enterprise
Java
@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;
}
v131202
Asynchronous EJB
22
Synchronous Example: Results
Enterprise
Java
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
v131202
Asynchronous EJB
23
Asynchronous Example: Client EJB
Enterprise
Java
@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));
}
v131202
Asynchronous EJB
24
Enterprise
Java
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);
}
v131202
Asynchronous EJB
25
Asynchronous Example: Results
Enterprise
Java
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
v131202
Asynchronous EJB
26
EJB Timers
Enterprise
Java
• 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
v131202
v111128
Asynchronous
EJB
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.ScheduleExpression
• @javax.ejb.Schedule
v131202
Asynchronous EJB
28
Declarative Calendar Timer
Enterprise
Java
@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);
}
}
v131202
Asynchronous EJB
29
Programmatic Calendar Timer
Enterprise
Java
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);
}
}
v131202
Asynchronous EJB
30
Programmatic Interval Timer
Enterprise
Java
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);
}
}
v131202
Asynchronous EJB
31
EJB Timers
Enterprise
Java
• 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
v131202
Asynchronous EJB
32
EJB Timer Callbacks
Enterprise
Java
• 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) {
...
}
}
v131202
Asynchronous EJB
33
javax.ejb.TimerService
Enterprise
Java
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 ...;
}
v131202
Asynchronous EJB
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
v131202
v111128
Asynchronous
EJB
Asynchronous EJB
3535
References
Enterprise
Java
• Java Messaging Service API
– http://java.sun.com/javaee/5/docs/api/javax/jms/packagesummary.html
• “Enterprise JavaBeans 3.0, 5th Edition”; Burke &
Monsen-Haefel; ISBN 0-596-00978-X; O'Reilly
v131202
Asynchronous EJB
36
Related documents