程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> J2EE >> Eclipse+JBoss+EJB3消息驅動Bean

Eclipse+JBoss+EJB3消息驅動Bean

編輯:J2EE

在前面的文章中給出的SessionBean的例子都是同步調用SessionBean方法的,也就是說,只有當方法中的代碼都執行完,才能返回到客戶端。但在某些情況下,由於SessionBean方法的執行時間比較長,這就需要異步地調用該方法,否則客戶端就需要等待比較長的時間。要實現異步調用,就需要使用本要講的消息驅動Bean。消息驅動Bean的基本原理是客戶端向消息服務器發送一條消息後,消息服務器會將該消息保存在消息隊列中。在這時消息服務器中的某個消費者(讀取並處理消息的對象)會讀取該消息,並進行處理。發送消息的客戶端被稱為消息生產者。

本文給出的消息驅動Bean的例子的基本功能是客戶端向消息服務器發送一條消息(該消息實際上是一個實體Bean的對象實例),然後消息消費者讀取這條消息後,將消息中的實體Bean持久化。實現消息驅動Bean的步驟如下:

一、實現實體Bean

  1. package entity;
  2. import Java.io.Serializable;
  3. import Java.util.Date;
  4. import Javax.persistence.Column;
  5. import Javax.persistence.Entity;
  6. import Javax.persistence.GeneratedValue;
  7. import Javax.persistence.GenerationType;
  8. import Javax.persistence.Id;
  9. import Javax.persistence.Table;
  10. @Entity
  11. @Table(name="t_date")
  12. public class DateBean implements Serializable
  13. {
  14. private int id;
  15. private Date myDate;
  16. @Id
  17. @GeneratedValue(strategy=GenerationType.IDENTITY)
  18. public int getId()
  19. {
  20. return id;
  21. }
  22. public void setId(int id)
  23. {
  24. this.id = id;
  25. }
  26. @Column(name="mydate")
  27. public Date getMyDate()
  28. {
  29. return myDate;
  30. }
  31. public void setMyDate(Date myDate)
  32. {
  33. this.myDate = myDate;
  34. }
  35. }

二、編寫消息驅動Bean

消息驅動Bean必須實現MessageListener接口,當該消息驅動Bean接收到一個消息後,EJB容器就會調用MessageListener接口的onMessage方法來理該消息。消息驅動Bean的代碼如下:

  1. package service;
  2. import Javax.ejb.ActivationConfigProperty;
  3. import Javax.ejb.EJBException;
  4. import Javax.ejb.MessageDriven;
  5. import Javax.jms.Message;
  6. import Javax.jms.MessageListener;
  7. import Javax.jms.ObjectMessage;
  8. import Javax.persistence.EntityManager;
  9. import Javax.persistence.PersistenceContext;
  10. import entity.DateBean;
  11. @MessageDriven( activationConfig = {
  12. @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "Javax.jms.Queue"),
  13. @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/MDBQueue")
  14. })
  15. public class DateMessageBean implements MessageListener
  16. {
  17. @PersistenceContext(unitName = "myentity1")
  18. private EntityManager em;
  19. @Override
  20. public void onMessage(Message message)
  21. {
  22. try
  23. {
  24. if(message instanceof ObjectMessage)
  25. {
  26. ObjectMessage objmsg = (ObjectMessage) message;
  27. DateBean dateBean = (DateBean) objmsg.getObject();
  28. em.persist(dateBean);
  29. System.out.println("成功持久化DateBean對象!");
  30. }
  31. else
  32. {
  33. System.out.println("消息類型錯誤!");
  34. }
  35. }
  36. catch (Exception e)
  37. {
  38. throw new EJBException(e);
  39. }
  40. }
  41. }

消息驅動Bean需要使用@MessageDriven進行注釋。要注意的是destination屬性的值是queue/MDBQueue。JBoss不會自已建立一個Queue對象,因此,需要手工來配置Queue對象。讀者可以\server\default\deploy目錄中建立一個xxx-service.xml文件,其中xxx可以任意取值,但必須跟“-service”後綴,例如,abc-service.XML。該文件可以放在deploy或其子目錄(可以是多層子目錄)中。該文件的內容如下:

  1. < XML version="1.0" encoding="UTF-8"?>
  2. < server>
  3. < mbean code="org.jboss.mq.server.jmx.Queue" name="jboss.mq.destination:service=Queue,name=MDBQueue">
  4. < depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManagerdepends>
  5. < mbean>
  6. < server>

要注意的是,元素的name屬性值中的name必須是MDBQueue,要與queue/MDBQueue中的/後面的部分一致。如果不進行上面的配置,在啟動JBOSS時就會拋出如下的異常:

Javax.naming.NameNotFoundException: MDBQueue not bound

也可以將元素放在deploy目錄中的其他以-service.XML結尾的文件中。

如果不設置destination屬性的值,在啟動JBoss是會拋出如下的異常:

  1. org.jboss.deployers.spi.DeploymentException: Required config property RequiredConfigPropertyMetaData@174098f[name=destination descriptions=[DescriptionMetaData@4ca30b[language=zh]]] for messagingType 'Javax.jms.MessageListener' not found in activation config [ActivationConfigProperty(destinationType=Javax.jms.Queue), ActivationConfigProperty(connectionFactoryJndiName=MyQueueConnectionFactory), ActivationConfigProperty(destinationName=MyRequestQueue)] ra=jboss.jca:service=RARDeployment,name='jms-ra.rar'
  2. ... ...

三、編寫調用消息驅動Bean的SessionBean

  1. package service;
  2. import Java.util.ArrayList;
  3. import Java.util.Date;
  4. import Java.util.List;
  5. import Javax.annotation.Resource;
  6. import Javax.ejb.Stateless;
  7. import Javax.jms.Connection;
  8. import Javax.jms.ConnectionFactory;
  9. import Javax.jms.MessageProducer;
  10. import Javax.jms.ObjectMessage;
  11. import Javax.jms.Queue;
  12. import Javax.jms.Session;
  13. import Javax.persistence.EntityManager;
  14. import entity.DateBean;
  15. import entity.Greeting;
  16. @Stateless
  17. public class GreeterBean implements Greeter
  18. {
  19. @Resource(mappedName = "ConnectionFactory")
  20. private ConnectionFactory cf;
  21. @Resource(mappedName = "queue/MDBQueue")
  22. private Queue queue;
  23. @Override
  24. public String greet(String message)
  25. {
  26. try
  27. {
  28. DateBean db = new DateBean();
  29. db.setMyDate(new Date());
  30. Connection connection = cf.createConnection();
  31. Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
  32. MessageProducer messageProducer = session.createProducer(queue);
  33. ObjectMessage objectMessage = session.createObjectMessage();
  34. objectMessage.setObject(db);
  35. messageProducer.send(objectMessage);
  36. connection.close();
  37. System.out.println("成功發送消息!");
  38. }
  39. catch (Exception e)
  40. {
  41. System.out.println("發送消息失敗!");
  42. }
  43. return "方法成功返回";
  44. }
  45. }

在上面的代碼中使用ObjectMessage對象來包裝要向消息服務器發送的實體Bean的對象實例。

除了可以在SessionBean中訪問消息驅動Bean外,還可以在不同的機器上通過jndi來查找並調用消息驅動Bean,代碼如下:

  1. package test;
  2. import Java.util.Date;
  3. import Javax.ejb.EJB;
  4. import Javax.jms.Destination;
  5. import Javax.jms.MessageProducer;
  6. import Javax.jms.ObjectMessage;
  7. import Javax.jms.Queue;
  8. import Javax.jms.QueueConnection;
  9. import Javax.jms.QueueConnectionFactory;
  10. import Javax.jms.QueueSession;
  11. import Javax.jms.TextMessage;
  12. import Javax.naming.InitialContext;
  13. import entity.DateBean;
  14. import service.Greeter;
  15. public class ClIEnt
  16. {
  17. public static void main(String[] args) throws Exception
  18. {
  19. InitialContext ctx = new InitialContext();
  20. QueueConnection connection = null;
  21. QueueSession session = null;
  22. QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup("ConnectionFactory");
  23. connection = factory.createQueueConnection();
  24. session = connection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
  25. Destination destination = (Queue) ctx.lookup("queue/MDBQueue");
  26. MessageProducer messageProducer = session.createProducer(destination);
  27. ObjectMessage objectMessage = session.createObjectMessage();
  28. DateBean db = new DateBean();
  29. db.setMyDate(new Date());
  30. objectMessage.setObject(db);
  31. messageProducer.send(objectMessage);
  32. connection.close();
  33. System.out.println("成功發送消息!");
  34. }
  35. }

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved