JBOSS7搭载EJB3之消息驱动Bean


  消息驱动bean(message driven bean)MDB--用于处理基于消息的组件


下面借用几张黎老师讲课的图片  很清晰  就直接上图了



队列方式 Queue  即点对点PTP  一个消息只能传递给一个接收者





环状方式  Topic  即pub/sub 发布/订阅  一条消息可以有多个接收方


对于jboss7中 默认的standalone中 是没有jms的配置的  但是standalone-full里面有jms的配置 所以将jboss-as-7.1.1.Finalstandaloneconfiguration 下的standalone-full.xml改为standalone.xml  即可  打开修改的文件 找到jms测试的queue、topic的目的地址的配置

<jms-destinations>
                    <jms-queue name="testQueue">
                        <entry name="queue/test"/>
                        <entry name="java:jboss/exported/jms/queue/test"/>
                    </jms-queue>
                    <jms-topic name="testTopic">
                        <entry name="topic/test"/>
                        <entry name="java:jboss/exported/jms/topic/test"/>
                    </jms-topic>
                </jms-destinations>

记住它的名字  一会在代码中要用

还有一个就是连接工厂

<jms-connection-factories>
                    <connection-factory name="InVmConnectionFactory">
                        <connectors>
                            <connector-ref connector-name="in-vm"/>
                        </connectors>
                        <entries>
                            <entry name="java:/ConnectionFactory"/>
                        </entries>
                    </connection-factory>
                    <connection-factory name="RemoteConnectionFactory">
                        <connectors>
                            <connector-ref connector-name="netty"/>
                        </connectors>
                        <entries>
                            <entry name="RemoteConnectionFactory"/>
                            <entry name="java:jboss/exported/jms/RemoteConnectionFactory"/>
                        </entries>
                    </connection-factory>
                    <pooled-connection-factory name="hornetq-ra">
                        <transaction mode="xa"/>
                        <connectors>
                            <connector-ref connector-name="in-vm"/>
                        </connectors>
                        <entries>
                            <entry name="java:/JmsXA"/>
                        </entries>
                    </pooled-connection-factory>
                </jms-connection-factories>



好了 现在开始使用PTP方式产生消息

package com.undergrowth.hello.impl;

import javax.annotation.Resource;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSession;
import javax.jms.TextMessage;

import com.undergrowth.hello.JmsMessProducer;


/**
 * 
 * @author Administrator
 *
 */
@Stateless
@Remote(JmsMessProducer.class)
public class JmsMessProducerBean implements JmsMessProducer {

	//注入连接工厂和目的地
	@Resource(mappedName="java:/ConnectionFactory")
	private QueueConnectionFactory conFactory;
	@Resource(mappedName="java:/queue/test")
	private Destination destination;
	
	@Override
	public void send(String what) {
		// TODO Auto-generated method stub
		QueueConnection queueConnection=null;
		QueueSession session=null;
		try {
			//创建队列连接
			 queueConnection=conFactory.createQueueConnection();
			 session=queueConnection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
			 //创建消息提供者
			MessageProducer producer=session.createProducer(destination);
			TextMessage message=session.createTextMessage(what);
			//发送消息
			producer.send(message);
			System.out.println(JmsMessProducerBean.class+":	发送的消息为:	"+message.getText());
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			try {
				session.close();
				queueConnection.close();
			} catch (JMSException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		
	}

}

远程接口

package com.undergrowth.hello;

/**
 * 消息的发送者
 * @author Administrator
 *
 */
public interface JmsMessProducer {
	public void send(String what);
}

使用MDB注册到JBOSS中 接收PTP消息

package com.undergrowth.hello.impl;

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

@MessageDriven(activationConfig={
		@ActivationConfigProperty(propertyName="destinationType",propertyValue="javax.jms.Queue"),
		@ActivationConfigProperty(propertyName="destination",propertyValue="java:/queue/test")
})
public class JmsMessageConsumer implements MessageListener {

	@Override
	public void onMessage(Message msg) {
		// TODO Auto-generated method stub
		TextMessage message=(TextMessage) msg;
		try {
			System.out.println(JmsMessageConsumer.class+":	接收到消息为:	"+message.getText());
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}


再看另一种方式  Topic  pub/sub

package com.undergrowth.hello.impl;

import javax.annotation.Resource;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.TextMessage;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicSession;

import com.undergrowth.hello.JmsMessTopicProducer;

@Stateless
@Remote(JmsMessTopicProducer.class)
public class JmsMessTopicProducerBean implements JmsMessTopicProducer{

	//注入连接工厂和目的地
		@Resource(mappedName="java:/ConnectionFactory")
		private TopicConnectionFactory conFactory;
		@Resource(mappedName="java:/topic/test")
		private Destination destination;
	
	@Override
	public void send(String what) {
		// TODO Auto-generated method stub
		TopicConnection connection=null;
		TopicSession session=null;
		try {
			 connection=conFactory.createTopicConnection();
			 session=connection.createTopicSession(false, TopicSession.AUTO_ACKNOWLEDGE);
			 MessageProducer producer=session.createProducer(destination);
			 TextMessage message=session.createTextMessage(what);
			 producer.send(message);
			 System.out.println(JmsMessTopicProducerBean.class+"	 发送的消息为:	"+what);
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			try {
				session.close();
				connection.close();
			} catch (JMSException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		
	}

}

远程接口

package com.undergrowth.hello;

public interface JmsMessTopicProducer extends JmsMessProducer{
		
}

使用多个消息驱动bean 来接收pub/sub 消息

package com.undergrowth.hello.impl;

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

@MessageDriven(activationConfig={
		@ActivationConfigProperty(propertyName="destinationType",propertyValue="javax.jms.Topic"),
		@ActivationConfigProperty(propertyName="destination",propertyValue="java:/topic/test")
})
public class JmsMessTopicConsumer implements MessageListener{

	@Override
	public void onMessage(Message msg) {
		// TODO Auto-generated method stub
		TextMessage message=(TextMessage) msg;
		try {
			System.out.println(JmsMessTopicConsumer.class+"	 接收到的消息为:	"+message.getText());
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
	
}

另外一个

package com.undergrowth.hello.impl;

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

@MessageDriven(activationConfig={
		@ActivationConfigProperty(propertyName="destinationType",propertyValue="javax.jms.Topic"),
		@ActivationConfigProperty(propertyName="destination",propertyValue="java:/topic/test")
})
public class JmsMessTopicConsumerOther implements MessageListener{

	@Override
	public void onMessage(Message msg) {
		// TODO Auto-generated method stub
		TextMessage message=(TextMessage) msg;
		try {
			System.out.println(JmsMessTopicConsumerOther.class+"	 接收到的消息为:	"+message.getText());
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
	
}


好了 服务端写好了 打包发布 ant 的build.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!-- ================================================ -->
<!-- Sample buildfile for jar components -->
<!-- -->
<!-- ================================================ -->
<project name="HelloWorld"  basedir=".">
    <!-- 定义属性 -->
    <property name="src.dir" value="${basedir}src" />
    <property environment="env"  />
    <property name="jboss.home" value="${env.JBOSS_HOME}"/>
    <property name="jboss.server.home" value="standalone"  />
    <property name="dep" value="deployments"  />
    <property name="build.dir" value="${basedir}uild"  />

    <path id="build.classpath">
    	<fileset dir="${basedir}lib">
    		<include name="*.jar" />
    	</fileset>
    	<pathelement location="${build.dir}" />
    </path>

	<!-- - - - - - - - - - - - - - -->
	<!-- target: init -->
	<!-- - - - - - - - - - - - - - -->
	<target name="init">
		<delete dir="${build.dir}"></delete>
		<mkdir dir="${build.dir}"></mkdir>
	</target>

	<!-- ========================= -->
	<!-- target: compile -->
	<!-- ========================= -->
	<target name="compile" depends="init"
		description="--> compile  this component" >

		<javac srcdir="${src.dir}" destdir="${build.dir}" includes="com/**">
			<classpath refid="build.classpath" />
		</javac>
	</target>
	
	<!-- 打包 -->
	<target name="ejbjar" depends="compile" description="打包ejb">
	   <jar jarfile="${basedir}${ant.project.name}.jar">
	   	<fileset dir="${build.dir}">
	   		<include name="**/*.class"></include>
	   	</fileset>
	   	<metainf dir="${src.dir}META-INF"></metainf>
	   </jar>
	</target>

    <!-- 部署 -->
    <target name="delopy" depends="ejbjar" description="部署ejb">
    	<copy file="${basedir}${ant.project.name}.jar"  todir="${jboss.home}${jboss.server.home}${dep}" />
    </target>
    
    <!-- 卸载ejb -->
    <target name="undeploy" description="卸载ejb">
      <delete file="${jboss.home}${jboss.server.home}${dep}${ant.project.name}.jar"></delete>
    </target>
    
	<!-- 打包接口 -->
	<target name="package_inter" depends="compile" description="打包接口">
		<jar jarfile="${basedir}${ant.project.name}Interface.jar">
			   	<fileset dir="${build.dir}">
			   		<exclude name="**/impl/*.class"></exclude>
			   	</fileset>
			   </jar>
	</target>
	
	

</project>


jboss 控制台

22:04:59,587 INFO  [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-3) JNDI bindings for session bean named JmsMessProducerBean in deployment unit deployment "HelloWorld.jar" are as follows:

	java:global/HelloWorld/JmsMessProducerBean!com.undergrowth.hello.JmsMessProducer
	java:app/HelloWorld/JmsMessProducerBean!com.undergrowth.hello.JmsMessProducer
	java:module/JmsMessProducerBean!com.undergrowth.hello.JmsMessProducer
	java:jboss/exported/HelloWorld/JmsMessProducerBean!com.undergrowth.hello.JmsMessProducer
	java:global/HelloWorld/JmsMessProducerBean
	java:app/HelloWorld/JmsMessProducerBean
	java:module/JmsMessProducerBean
22:04:59,576 INFO  [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-3) JNDI bindings for session bean named JmsMessTopicProducerBean in deployment unit deployment "HelloWorld.jar" are as follows:

	java:global/HelloWorld/JmsMessTopicProducerBean!com.undergrowth.hello.JmsMessTopicProducer
	java:app/HelloWorld/JmsMessTopicProducerBean!com.undergrowth.hello.JmsMessTopicProducer
	java:module/JmsMessTopicProducerBean!com.undergrowth.hello.JmsMessTopicProducer
	java:jboss/exported/HelloWorld/JmsMessTopicProducerBean!com.undergrowth.hello.JmsMessTopicProducer
	java:global/HelloWorld/JmsMessTopicProducerBean
	java:app/HelloWorld/JmsMessTopicProducerBean
	java:module/JmsMessTopicProducerBean



第三方客户端测试

queue测试

package com.undergrowth.ejb3.client;

import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.undergrowth.hello.HelloWorldLocal;
import com.undergrowth.hello.JmsMessProducer;

public class JmsClient {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			JmsMessProducer messProducer=lookupRemoteHelloWorldBean();
			messProducer.send("jms文本消息,明天又要上班了!!!");
		} catch (NamingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	 public static JmsMessProducer lookupRemoteHelloWorldBean() throws NamingException {
	        final Hashtable jndiProperties = new Hashtable();
	        jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
	        final Context context = new InitialContext(jndiProperties);
	        // The app name is the application name of the deployed EJBs. This is typically the ear name
	        // without the .ear suffix. However, the application name could be overridden in the application.xml of the
	        // EJB deployment on the server.
	        // Since we haven't deployed the application as a .ear, the app name for us will be an empty string
	        final String appName = "";
	        // This is the module name of the deployed EJBs on the server. This is typically the jar name of the
	        // EJB deployment, without the .jar suffix, but can be overridden via the ejb-jar.xml
	        // In this example, we have deployed the EJBs in a jboss-as-ejb-remote-app.jar, so the module name is
	        // jboss-as-ejb-remote-app
	        final String moduleName = "HelloWorld";
	        // AS7 allows each deployment to have an (optional) distinct name. We haven't specified a distinct name for
	        // our EJB deployment, so this is an empty string
	        final String distinctName = "";
	        // The EJB name which by default is the simple class name of the bean implementation class
	        final String beanName = "JmsMessProducerBean";
	        // the remote view fully qualified class name
	       // final String viewClassName = HelloWorldRemote.class.getName();
	        final String viewClassName = JmsMessProducer.class.getName();
	        // let's do the lookup
	        return (JmsMessProducer) context.lookup("ejb:" + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName);
	        
	 }
	 
	
}

控制台

22:10:18,816 INFO  [stdout] (EJB default - 3) class com.undergrowth.hello.impl.JmsMessProducerBean:	发送的消息为:	jms文本消息,明天又要上班了!!!

22:10:19,226 INFO  [stdout] (Thread-162 (HornetQ-client-global-threads-28566125)) class com.undergrowth.hello.impl.JmsMessageConsumer:	接收到消息为:	jms文本消息,明天又要上班了!!!

看下jboss的管理控制台



队列消息添加1  运行一次客户端  加一次


topic方式 测试

package com.undergrowth.ejb3.client;

import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.undergrowth.hello.HelloWorldLocal;
import com.undergrowth.hello.JmsMessProducer;
import com.undergrowth.hello.JmsMessTopicProducer;

public class JmsTopicClient {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			JmsMessProducer messProducer=lookupRemoteHelloWorldBean();
			messProducer.send("jms的topic方式文本消息,明天又要上班了!!!");
		} catch (NamingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	 public static JmsMessTopicProducer lookupRemoteHelloWorldBean() throws NamingException {
	        final Hashtable jndiProperties = new Hashtable();
	        jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
	        final Context context = new InitialContext(jndiProperties);
	        // The app name is the application name of the deployed EJBs. This is typically the ear name
	        // without the .ear suffix. However, the application name could be overridden in the application.xml of the
	        // EJB deployment on the server.
	        // Since we haven't deployed the application as a .ear, the app name for us will be an empty string
	        final String appName = "";
	        // This is the module name of the deployed EJBs on the server. This is typically the jar name of the
	        // EJB deployment, without the .jar suffix, but can be overridden via the ejb-jar.xml
	        // In this example, we have deployed the EJBs in a jboss-as-ejb-remote-app.jar, so the module name is
	        // jboss-as-ejb-remote-app
	        final String moduleName = "HelloWorld";
	        // AS7 allows each deployment to have an (optional) distinct name. We haven't specified a distinct name for
	        // our EJB deployment, so this is an empty string
	        final String distinctName = "";
	        // The EJB name which by default is the simple class name of the bean implementation class
	        final String beanName = "JmsMessTopicProducerBean";
	        // the remote view fully qualified class name
	       // final String viewClassName = HelloWorldRemote.class.getName();
	        final String viewClassName = JmsMessTopicProducer.class.getName();
	        // let's do the lookup
	        return (JmsMessTopicProducer) context.lookup("ejb:" + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName);
	        
	 }
	 
	
}


控制台

22:13:45,928 INFO  [stdout] (EJB default - 5) class com.undergrowth.hello.impl.JmsMessTopicProducerBean	 发送的消息为:	jms的topic方式文本消息,明天又要上班了!!!

22:13:45,931 INFO  [stdout] (Thread-170 (HornetQ-client-global-threads-28566125)) class com.undergrowth.hello.impl.JmsMessTopicConsumerOther	 接收到的消息为:	jms的topic方式文本消息,明天又要上班了!!!

22:13:45,938 INFO  [stdout] (Thread-174 (HornetQ-client-global-threads-28566125)) class com.undergrowth.hello.impl.JmsMessTopicConsumer	 接收到的消息为:	jms的topic方式文本消息,明天又要上班了!!!


两个接收者都收到消息了


jboss管理界面






好了 

参看文档:

http://my.oschina.net/zhaoqian/blog/90796

http://dujianmeng.iteye.com/blog/1552685




记录学习的脚步  

原文地址:https://www.cnblogs.com/liangxinzhi/p/4275552.html