ejb2.0消息驱动bean的开发(JBOSS4.0.4.GA 环境)

 

          消息驱动bean主要使用在异步的业务中,比如用户在页面上查询了话费(余额,实时话费,语音,短信。。。),我们需要把用户这个行为记录到数据库中,就可以使用消息驱动bean。

           首先使用springAOP 拦截到 调用的 业务方法,发现是业务关注的方法的时候,在invoke 方法中发送一条消息到消息队列中去,(此业务场景我们使用 点对点的 消息发送模式)然后 ,消息驱动bean从监听的队列中取到消息,插入到数据库中。查询话费 和 将行为入库 是异步的,因此不会阻塞。不影响前台页面显示速度。

 

 

开发一个消息驱动bean 的步骤:

 

 

1.首先 写 消息驱动bean ,负责从消息队列中取消息,然后执行相应的业务方法

 

 

package cn.com.xinli.ejb.mdb;
import javax.ejb.EJBException;
import javax.ejb.MessageDrivenBean;
import javax.ejb.MessageDrivenContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

import org.apache.log4j.Logger;

public class MDBean implements MessageDrivenBean,MessageListener
{
	Logger log=Logger.getLogger(MDBean.class);
	private transient MessageDrivenContext mdc = null;
	public void onMessage(Message message)
	{		
		if(message instanceof TextMessage)
		{
			TextMessage msg=(TextMessage) message; 
			try {
				log.info("接收到消息:"+msg.getText());
			} catch (JMSException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		else
		{
			log.info("消息类型不正确!"); 
		}
	}
	 public void ejbCreate() 
	 {
		  
	 }
	public void ejbRemove() throws EJBException
	{
		// TODO Auto-generated method stub
		
	}
	public void setMessageDrivenContext(MessageDrivenContext mdc)
			throws EJBException
	{
		this.mdc = mdc;
		// TODO Auto-generated method stub
	}

}

 

 

2. 配置 ejb-jar.xml

 

<?xml version="1.0" encoding="gb2312"?> 
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" 
"http://java.sun.com/dtd/ejb-jar_2_0.dtd">
<ejb-jar>
	<description>ejb</description>
	<display-name>myEJBTest</display-name>
<enterprise-beans>

		
			<message-driven id="ejb_mdb">
			<ejb-name>mdb</ejb-name>
            <ejb-class>cn.com.xinli.ejb.mdb.MDBean</ejb-class>
           	<transaction-type>Bean</transaction-type>
           	<acknowledge-mode>Auto-acknowledge</acknowledge-mode>
           	<message-driven-destination>
            <destination-type>javax.jms.Queue</destination-type> 
            </message-driven-destination>
		</message-driven>
	</enterprise-beans>
</ejb-jar>

 

 

3. 配置 jboss.xml

 

<?xml version="1.0" encoding="gb2312"?>
<jboss>
	
	<message-driven>
        <ejb-name>mdb</ejb-name>    
        <configuration-name>Standard Message Driven Bean</configuration-name>
        <!-- 消息驱动bean 监听的消息队列的 JNDI
        <destination-jndi-name>queue/mdb</destination-jndi-name>  
        -->
      </message-driven> 
	</enterprise-beans>
</jboss>

 

 

4. 讲bean 打成jar包 放在 D:\jboss-4.0.4.GA\server\default\deploy 下

 

5. 在jboss中配置消息队列 也在 D:\jboss-4.0.4.GA\server\default\deploy 下 ,配置文件必须 符合  *-service.xml  的命名规范,这里我们叫 bsn-service.xml

 

<?xml version="1.0" encoding="UTF-8"?>

<!-- $Id: jbossmq-destinations-service.xml,v 1.4.6.1 2004/11/16 04:32:39 ejort Exp $ -->

<!-- 
   | This file defines the default Queues and Topics that JBossMQ
   | ships with.  The default Queues and Topics are used by the 
   | JBoss test suite and by the sample jms programs.
   |
   | You can add other destinations to this file, or you can create other
   | *-service.xml files to contain your application's destinations.
 -->

<server>
  <!-- Destination without a configured SecurityManager or without a 
       a SecurityConf will default to role guest with read=true, write=true,
       create=false.
  -->
  <mbean code="org.jboss.mq.server.jmx.Queue" 
	 name="jboss.mq.destination:service=Queue,name=queueRecordb">
	  <attribute name="JNDIName">queue/mdb</attribute> 
   <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
  </mbean>
</server>

  

 

6.发布

 

7.客户端测试,观察 JBOSS 控制台 会有

 

09:43:36,156 INFO  [MDBean] 接收到消息:你好

 

package cn.com.xinli.ejb.test;

import java.util.Properties;

import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSession;
import javax.jms.TextMessage;
import javax.naming.InitialContext;

import org.apache.log4j.Logger;

public class Test
{

	static Logger log=Logger.getLogger(Test.class);
	/**
	 * @param args
	 */
	public static void main(String[] args)
    {
		
       
        Properties props = new Properties();
        props.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
        props.setProperty("java.naming.provider.url", "localhost:1099");
        props.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming");
        try
        {
            InitialContext ctx = new InitialContext(props);
            
        	QueueConnectionFactory factory=(QueueConnectionFactory)ctx.lookup("QueueConnectionFactory");
			QueueConnection conn=factory.createQueueConnection();
			
			QueueSession session=conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
			
			Destination destination=(Destination)ctx.lookup("queue/mdb");
			MessageProducer producer = session.createProducer(destination);
			
			TextMessage msg = session.createTextMessage("你好");
			producer.send(msg);
			log.info("发送消息成功!!");
            
            /*
            Object objRef = ctx.lookup("helloEJB");
            
            HelloWorldHome home = (HelloWorldHome) PortableRemoteObject.narrow(objRef, HelloWorldHome.class);
            
            HelloWorldRemote remote = home.create();
            
            log.info(remote.sayHello());
            */
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }
}

  

 

备注:

 

1. 许多教程上说 必须要到   D:\jboss-4.0.4.GA\server\default\deploy  配置一个 消息队列 类似 bsn-service.xml

    其实这不是必要的

 

如果我们没有配置  a ,b

a.     <!-- 消息驱动bean 监听的消息队列的 JNDI-->
        <destination-jndi-name>queue/mdb</destination-jndi-name> 

b.   也没有配置 bsn-service.xml 那么JBOSS启动的时候发现没有队列和消息驱动bean 关联,则它会自己创建一个消息队列 ,这个消息对列的命名规范 是   : queue/消息驱动bean的jndi

 

      客户端就可以往这个队列 上发送消息。

 

2. 如果我们配置了 消息驱动bean 关联的队列 和 JBosS下的 bsn-service.xml ,那么我们就可以使用自定义的 队列的JNDI了 比如

 

  a. 配置 mdb 这个消息驱动bean 监听的 对列的JNDI 为

<destination-jndi-name>myqueue</destination-jndi-name> 

 

b.配置 bsn-service.xml的内容为

 

<?xml version="1.0" encoding="UTF-8"?>

<!-- $Id: jbossmq-destinations-service.xml,v 1.4.6.1 2004/11/16 04:32:39 ejort Exp $ -->

<!-- 
   | This file defines the default Queues and Topics that JBossMQ
   | ships with.  The default Queues and Topics are used by the 
   | JBoss test suite and by the sample jms programs.
   |
   | You can add other destinations to this file, or you can create other
   | *-service.xml files to contain your application's destinations.
 -->

<server>
  <!-- Destination without a configured SecurityManager or without a 
       a SecurityConf will default to role guest with read=true, write=true,
       create=false.
  -->
  <mbean code="org.jboss.mq.server.jmx.Queue" 
	 name="jboss.mq.destination:service=Queue,name=queueRecordb">
	  <attribute name="JNDIName">myqueue</attribute> 
   <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
  </mbean>
</server>

  

 

 

 

 

那么客户端就可以往 我们自定义的 队列的JDNI上  myqueue  发送消息了

 

3.  在JBOSS中有两个默认的工厂 一个是 QueueConnectionFactory

另外一个是 TopicConnectionFactory ,这两个工厂是由JBOSS容器帮我们建立的 ,不需要我们去配置,而在websphere 上建立消息驱动bean的时候 就需要我们配置 连接工厂了

 

4. 以上模拟的的消息驱动bean 是队列模式 ,主题模式何其类似 

 


附件中式 全部的工程代码

 

 

 

 

 

 

你可能感兴趣的:(bean,xml,jboss,jms,ejb)