现在的位置: 首页 > 综合 > 正文

EJB3.0消息驱动Bean

2018年05月09日 ⁄ 综合 ⁄ 共 5156字 ⁄ 字号 评论关闭

一、工程环境
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
HTTP
访问端口

Tomcat AJP/1.3 Connector

AJP

8009

作为Apache
tomcat

连接器
mod_jk的连接端口

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远程访问协议

 

抱歉!评论已关闭.