一、工程环境
Myeclipse6.5.1 GA, jboss-5.1.0.GA
二、消息驱动Bean(MyMDBBean.java)
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="queue/myqueue")
}
)
public class MyMDBBean implements MessageListener {
public void onMessage(Message msg) {
TextMessage textMessage = (TextMessage) msg;
try {
System.out.println("消息驱动Bean被调用了,【"+textMessage.getText()+"】");
} catch (JMSException e) {
e.printStackTrace();
}
}
}
将此消息驱动Bean部署到JBOSS上老报错:
Attempting to reconnect org.jboss.resource.adapter.jms.inflow.JmsActivationSpec@90265b(ra=org.jboss.resource.adapter.jms.JmsResourceAdapter@1280e84 destination=queue/myqueue destinationType=javax.jms.Queue tx=true durable=false reconnect=10 provider=java:/DefaultJMSProvider
user=null maxMessages=1 minSession=1 maxSession=15 keepAlive=60000 useDLQ=true DLQHandler=org.jboss.resource.adapter.jms.inflow.dlq.GenericDLQHandler DLQJndiName=queue/DLQ DLQUser=null DLQMaxResent=5)
Unable to reconnect org.jboss.resource.adapter.jms.inflow.JmsActivationSpec@90265b(ra=org.jboss.resource.adapter.jms.JmsResourceAdapter@1280e84 destination=queue/myqueue destinationType=javax.jms.Queue tx=true durable=false reconnect=10 provider=java:/DefaultJMSProvider
user=null maxMessages=1 minSession=1 maxSession=15 keepAlive=60000 useDLQ=true DLQHandler=org.jboss.resource.adapter.jms.inflow.dlq.GenericDLQHandler DLQJndiName=queue/DLQ DLQUser=null DLQMaxResent=5)
javax.naming.NameNotFoundException:
myqueue not bound
后来到网上google了一下,用以下方法可以解决:
在JBoss5.x根目录\server\default\deploy下的mail-service.xml文件中加入如下:
<mbean code="org.jboss.mq.server.jmx.Queue"
name="jboss.org.destination:server=Queue,name=myqueue" >
<attribute name="JNDIName" >queue/myqueue</attribute>
<depends optional-attribute-name = "DestinationManager" >
jboss.mq:service=DestinationManager
</depends>
</mbean>
或者
消息驱动Bean需要使用@MessageDriven进行注释。要注意的是destination属性的值是queue/MDBQueue。JBoss不会自已建立一个Queue对象,因此,需要手工来配置Queue对象。读者可以\server\default\deploy目录中建立一个xxx-service.xml文件,其中xxx可以任意取值,但必须跟“-service”后缀,例如,abc-service.xml。该文件可以放在deploy或其子目录(可以是多层子目录)中。该文件的内容如下:
然后重新启动JBOSS即可解决.
三、客户端如下
import java.util.Properties;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.TextMessage;
import javax.naming.InitialContext;
public class MyMdbClient {
public static void main(String [] args) throws Exception {
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");
InitialContext init = new InitialContext(props);
//创建ConnectionFactory
QueueConnectionFactory factory = (QueueConnectionFactory) init.lookup("ConnectionFactory");
//创建Connection
QueueConnection connection = factory.createQueueConnection();
//创建session,第一个参数:true标识手动提交,false表示事物自动提交;
//第二个参数表示一旦消息被正确送达,将自动发回响应
QueueSession session = connection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
//查找queue(destination)
Queue queue = (Queue) init.lookup("queue/myqueue");
//创建TextMessage
TextMessage msg = session.createTextMessage("消息驱动Bean跑起来了");
QueueSender sender = session.createSender(queue);
//利用QueueSender发送TextMessage
sender.send(msg);
session.close();
System.out.println("消息已被发送");
}
}
客户端的编写开始没有代码中的红色部分,运行后会报如下错误:
Exception in thread "main" javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
原因:在客户端工程的src下,没有提供jndi.properties
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost
加上红色部分的代码会正常运行:
后台打印结果:消息驱动Bean被调用了,【消息驱动Bean跑起来了】
客户端会打印:消息已被发送
四、总结
(1)将消息驱动Bean的声明中的destination的名字改变后,在mail-service.xml中的名字要做相应的修改,不然同样会报myMessageDrivenBean
not bound的错误。
@MessageDriven(
activationConfig = {
@ActivationConfigProperty(propertyName="destinationType",propertyValue="javax.jms.Queue"),
@ActivationConfigProperty(propertyName="destination",propertyValue="queue/myMessageDrivenBean")
}
)
因此,每开发一个消息驱动Bean,就要到mail-service.xml中增加一段相应的文本(网上别人说这是为了让消息驱动Bean能找到目标地址,还没找到其他更好的方法)
(2)在客户端的开发中需要增加一句props.setProperty("java.naming.provider.url", "localhost:1099");
开始将1099写成的是JBOSS的HTTP端口号:8888(自己修改的),但还是有问题,改成1099后正常运行。
见以下表格中JBOSS常用端口的作用:
服务 |
协议 |
默认端口 |
用途 |
Tomcat HTTP/1.1 Connector |
HTTP |
8080 |
作为最终用户的Web |
Tomcat AJP/1.3 Connector |
AJP |
8009 |
作为Apache |
Jboss Naming bootstrap JNP service |
JNP |
1099 |
Jboss命名服务JNP协议的监听入口 |
Jboss Naming RMI Port |
RMI |
1098 |
Jboss命名服务的RMI访问端口 |
RMI/JRMP Invoker |
JRMP |
4444 |
供RMI使用的标准Java远程方法协议 |
RMI/Pooled Invoker |
Socket |
4445 |
Jboss提供的RMI远程访问协议 |