230 likes | 371 Views
Module 6. Message-Driven Beans. History. Introduced in EJB 2.0 Supports processing of asynchronous messages from a JMS provider Definition expanded in EJB 2.1 Supports any messaging system Annotations introduced in EJB 3.0. JMS and Message-Driven Beans.
E N D
Module 6 Message-Driven Beans
History • Introduced in EJB 2.0 • Supports processing of asynchronous messages from a JMS provider • Definition expanded in EJB 2.1 • Supports any messaging system • Annotations introduced in EJB 3.0
JMS and Message-Driven Beans • All EJB 3.0 vendors must support a JMS provider • JMS • Vendor neutral API used to access enterprise messaging systems • Similar in concept to JDBC
JMS Terminology • JMS Client • Applications that use JMS • JMS Provider • System that handles routing and delivery of messages • JMS Application • Business system composed of many JMS clients and typically one JMS provider • Producer • JMS client that sends a message • Consumer • JMS client that receives a message
JMS in Action • EJBs of all type can use JMS to send messages • Messages consumed by other application or message-driven beans
Example using JMS • TravelAgentBean @Resource(mappedName=“ConnectionFactoryNameGoesHere”) private ConnectionFactory connectionFactory; @Resource(mappedName=“TicketTopic”) private Topic topic; @Remove public TicketDO bookFlight (CreditCardDO card, double price) throws IncompleteConversationalState { if(customer == null || flight == null || seat == null) throw new IncompleteConversationalState();
Example using JMS • TravelAgentBean try { Reservation reservation = new Reservation( customer, flight, seat, price, new Date()); entityManager.persist(reservation); process.byCredit(customer,card,price); TicketDO ticket = new TicketDO(customer, flight, seat, price); Connection connect = connectionFactory.createConnection(); Session session = connect.createSession(true,0); MessageProducer producer = session.createProducer(topic); TextMessage textMsg = session.createTextMessage(); textMsg.setText(ticket.description); producer.send(textMsg); connect.close(); return ticket; } catch(Exception e) { throw new EJBException(e); } }
Message Types • JMS Message is a Java Object • Header • Delivery Information and Metadata • Message Body • Text • Serializable Objects • Byte Streams • Other application data
Example using MapMessage • TravelAgentBean try { …… TicketDO ticket = new TicketDO(customer, flight, seat, price); …… MessageProducer producer = session.createProducer(topic); MapMessage mapMsg = session.createMapMessage(); mapMsg.setInt(“CustomerID”, ticket.customerID.intValue()); mapMsg.setInt(“FlightID”, ticket.flightID.intValue()); mapMsg.setInt(“SeatID”, ticket.seatID.intValue()); mapMsg.setDouble(“Price”, ticket.price); producer.send(mapMsg); …… }
JMS is Asynchronous • JMS client can send a message without having to wait for a reply • Synchronous communication requires tight coupling between client and EJB • Asynchronous communication decouples senders from receivers
JMS Messaging Models • Publish-and-Subscribe (pub/sub) • One-to-Many broadcast • Topic • Push-based model • Point-to-Point (p2p) • One-to-One delivery • Queue • Pull- or Polling-based model
Session Beans Should not Receive Messages • Session beans (or entities) cannot be programmed to respond to JMS messages • Can set up a business method that attempts to consume a JMS message but: • Method must be invoked synchronously from EJB client • Method prone to blocking if no message available • Bottom Line: Use Message-Driven Beans instead!
Message-Driven Beans • EJB • But no remote or local interface • Stateless • Server-Side • Transaction-Aware • Processes Asynchronous Messages • Concurrent behavior because container creates numerous instances
Message-Driven Bean • ReservationProcessorBean package edu.weber.reservationprocessor; import javax.jms.*; import edu.weber.domain.*; import edu.weber.processpayment.*; import edu.weber.travelagent.*; import java.util.Date; import javax.ejb.*; import javax.annotation.*; import javax.persistence.*; @MessageDriven(activationConfig={ @ActivationConfigProperty( propertyName=“destinationType”, propertyValue=“javax.jms.Queue”), @ActivationConfigProperty( propertyName=“messageSelector”, propertyValue=“MessageFormat=‘Version 3.4’”), @ActivationConfigProperty( propertyName=“acknowledgeMode”, propertyValue=“Auto-acknowledge”)})
Message-Driven Bean • ReservationProcessorBean public class ReservationProcessBean implements javax.jms.MessageListener { @PersistenceContext(unitName=“titanDB) private EntityManager em; @EJB private ProcessPaymentLocal process; @Resource(mappedName=“ConnectionFactory”) private ConnectionFactory connectionFactory;
Message-Driven Bean • ReservationProcessorBean public void onMessage(Message message) { try{ MapMessage reservationMsg = (MapMessage)message; int customerPk = reservationMsg.getInt(“CustomerID”); int flightPk = reservationMsg.getInt(“FlightID”); int seatPk = reservationMsg.getInt(“SeatID”); double price = reservationMsg.getDouble(“Price”); // get the credit card Date expirationDate = new Date(reservationMsg.getLong(“CreditCardExpDate”); String cardNumber = reservationMsg.getString(“CreditCardNum”); String cardType = reservationMsg.getString(“CreditCardType”); CreditCardDO card = new CreditCardDO(cardNumber, expirationDate, cardType);
Message-Driven Bean • ReservationProcessorBean Customer customer = em.find(Customer.class, customerPk); Flight flight = em.find(Flight.class, flightPk); Seat seat = em.find(Seat.class, seatPk); Reservation reservation = new Reservation(customer, flight, seat, price, new Date()); em.persist(reservation); process.byCredit(customer, card, price); TicketDO ticket = new TicketDO(customer, cruise, cabin, price); deliverTicket(reservationMsg, ticket); } catch (Exception e) { throw new EJBException(e); } }
MessageDrivenContext • Extends EJBContext • No new methods added
Message-Driven Bean • ReservationProcessorBean public void deliverTicket(MapMessage reservationMsg, TicketDO ticket) throws JMSException { Queue queue = (Queue)reservationMsg.getJMSReplyTo(); Connection connect = connectionFactory.createConnection(); Session session = connect.createSession(true, 0); MessageProducer sender = session.createProducer(queue); ObjectMessage message = session.createObjectMessage(); message.setObject(ticket); sender.send(message); connect.close(); }
Message-Driven Bean Lifecycle Does Not Exist Method-Ready Pool
Message-Driven Bean Lifecycle Does Not Exist Class.newInstance() injections @PostConstruct Method-Ready Pool
Message-Driven Bean Lifecycle Does Not Exist @PreDestroy Method-Ready Pool
Message-Driven Bean Lifecycle Method-Ready Pool Business Methods