MDB没有从无状态会话bean接收消息

时间:2014-02-15 20:34:13

标签: java jms ejb-3.1 jboss6.x message-driven-bean

我使用无状态bean作为JMS消息生成器:

package com.cts.businesslogic;

import javax.annotation.Resource;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.Session;

import com.cts.business.HelloWorldBeanRemote;
import com.cts.to.Customer;

/**
 * Session Bean implementation class HelloWorldBean
 */
@Stateless(name = "HelloWorldBean")
@LocalBean
public class HelloWorldBean implements HelloWorldBeanRemote {

    @Resource(name = "java:/ConnectionFactory")
    private ConnectionFactory connectionFactory;

    @Resource(name = "java:/jms/HelloWorldQueue")
    private Queue destination;

    private Connection connection;

    private MessageProducer producer;

    /**
     * Default constructor.
     */
    public HelloWorldBean() {
    }

    @Override
    public String sayHello() {

        try {
            connection = connectionFactory.createConnection();
            Session session = connection.createSession(true,
                    Session.AUTO_ACKNOWLEDGE);

            producer = session.createProducer(destination);

            ObjectMessage message = session.createObjectMessage();
            Customer c = new Customer();
            c.setName("John");
            message.setObject(c);
            producer.send(destination, message);

            session.close();
            connection.close();

        } catch (JMSException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return "Hello World : First Ejb";
    }

}

我的MDB如下:

package com.cts.businesslogic;

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

import com.cts.to.Customer;

/**
 * Message-Driven Bean implementation class for: HelloWorldMDB
 */
@MessageDriven(activationConfig = {
        @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
        @ActivationConfigProperty(propertyName = "destination", propertyValue = "jms/HelloWorldQueue") }, mappedName = "jms/HelloWorldQueue")
public class HelloWorldMDB implements MessageListener {

    /**
     * Default constructor.
     */
    public HelloWorldMDB() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @see MessageListener#onMessage(Message)
     */
    public void onMessage(Message message) {
        ObjectMessage o = (ObjectMessage) message;

        try {
            Customer c = (Customer) o.getObject();
            System.out.println("Hi " + c.getName()
                    + ". We received your message.");
        } catch (JMSException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}

我使用远程客户端调用无状态bean:

package com.cts.ejbclient;

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

import com.cts.business.HelloWorldBeanRemote;

public class EjbClient {

    private static final String LOOKUP_STRING = "FIRST_EJB/HelloWorldBean!com.cts.business.HelloWorldBeanRemote";

    public static void main(String[] args) {
        HelloWorldBeanRemote bean = doLookup();
        // 3. Call business logic
        System.out.println(bean.sayHello());
    }

    private static HelloWorldBeanRemote doLookup() {
        Context context = null;
        HelloWorldBeanRemote bean = null;
        try {
            // 1. Obtaining Context
            context = ClientUtility.getInitialContext();
            // 2. Lookup and cast
            bean = (HelloWorldBeanRemote) context.lookup(LOOKUP_STRING);
        } catch (NamingException e) {
            e.printStackTrace();
        }
        return bean;
    }
}

ClientUtility如下:

package com.cts.ejbclient;

import java.util.Properties;

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

public class ClientUtility {
    /*
     * location of JBoss JNDI Service provider the client will use. It should be
     * URL string.
     */
    private static final String PROVIDER_URL = "remote://localhost:4447";

    /*
     * Factory that creates initial context objects. fully qualified class name.
     */
    private static final String INITIAL_CONTEXT_FACTORY = "org.jboss.naming.remote.client.InitialContextFactory";

    private static Context initialContext;

    public static Context getInitialContext() throws NamingException {
        if (initialContext == null) {
            // Properties extends HashTable
            Properties prop = new Properties();
            prop.put(Context.INITIAL_CONTEXT_FACTORY, INITIAL_CONTEXT_FACTORY);
            //prop.put(Context.URL_PKG_PREFIXES, JNP_INTERFACES);
            prop.put(Context.PROVIDER_URL, PROVIDER_URL);
            prop.put("jboss.naming.client.ejb.context", true);
            prop.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
            prop.put(Context.SECURITY_PRINCIPAL, "admin");
            prop.put(Context.SECURITY_CREDENTIALS, "xxx");
            initialContext = new InitialContext(prop);
        }
        return initialContext;
    }
}

我面临的问题是,我可以从Hermen Jms监控工具中调用此MDB。但是当我运行上面提到的EJBClient时,我在eclipse中看到了服务器控制台:

01:52:11,198 INFO  [org.jboss.as.naming] (Remoting "xxx-pc" task-1) JBAS011806: Channel end notification received, closing channel Channel ID 17efc189 (inbound) of Remoting connection 6b8a3fef to null

控制台中没有其他行。在这种情况下,MDB不会被调用。

更多信息: 服务器 - JBOSS EAP 6.1

独立描述符 - standalone-full.xml

我试图找出实际问题,但不能。如果你知道这里有什么问题,请告诉我。 感谢。

1 个答案:

答案 0 :(得分:3)

我找到了这个神秘问题的解决方案。我将HelloWorldBean中的create session语句修改为:

Session session = connection.createSession(false,
                Session.AUTO_ACKNOWLEDGE);

我在Oracle API Documentation

中找到了以下参考资料

它说:

  • 如果transacted设置为true,则会话将使用本地事务,该事务随后可以通过调用会话的提交或回滚方法来提交或回滚。参数acknowledgeMode被忽略。

  • 如果transacted设置为false,则会话将不进行交易。在这种情况下,参数acknowledgeMode用于指定如何确认此会话接收的消息。允许的值是Session.CLIENT_ACKNOWLEDGE,Session.AUTO_ACKNOWLEDGE和Session.DUPS_OK_ACKNOWLEDGE。有关这些确认模式含义的定义,请参阅以下链接。

希望这个解决方案能够帮助他人。

[注意:我仍然收到警告说已收到频道结束通知。但正如迈克米尔所指出的那样,这个消息是无害的。感谢mikemil的合作。]