Java ActiveMQ与嵌入式代理

Java ActiveMQ与嵌入式代理,java,jms,activemq,Java,Jms,Activemq,编辑:重新表述问题: 我想将ActiveMQ用作服务器和客户端应用程序之间的messenger服务 我正在尝试在服务器内设置一个嵌入式代理(即,不是一个单独的进程),以处理生成的消息,供我的客户端使用。此队列被持久化 经纪人的初始化如下: BrokerService broker = new BrokerService(); KahaPersistenceAdapter adaptor = new KahaPersistenceAdapter(); adaptor.setDirectory(ne

编辑:重新表述问题:

我想将ActiveMQ用作服务器和客户端应用程序之间的messenger服务

我正在尝试在服务器内设置一个嵌入式代理(即,不是一个单独的进程),以处理生成的消息,供我的客户端使用。此队列被持久化

经纪人的初始化如下:

BrokerService broker = new BrokerService();
KahaPersistenceAdapter adaptor = new KahaPersistenceAdapter();
adaptor.setDirectory(new File("activemq"));
broker.setPersistenceAdapter(adaptor);
broker.setUseJmx(true);
broker.addConnector("tcp://localhost:61616");
broker.start();
经过修补,我最终得到的服务器部分是:

public static class HelloWorldProducer implements Runnable {
    public void run() {
        try {
            ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost"); // apparently the vm part is all i need
            Connection connection = connectionFactory.createConnection(); 
            connection.start();
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            Destination destination = session.createQueue("TEST.FOO");
            MessageProducer producer = session.createProducer(destination);
            producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
            String text = "Hello world! From: " + Thread.currentThread().getName() + " : " + this.hashCode();
            TextMessage message = session.createTextMessage(text);
            System.out.println("Sent message: "+ message.hashCode() + " : " + Thread.currentThread().getName());
            producer.send(message);
            session.close();
            connection.close();
        }
        catch (Exception e) {
            System.out.println("Caught: " + e);
            e.printStackTrace();
        }
    }
}
客户机非常相似,如下所示:

public static class HelloWorldConsumer implements Runnable, ExceptionListener {
    public void run() {
        try {
          ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost");
            Connection connection = connectionFactory.createConnection(); // exception happens here...
            connection.start();
            connection.setExceptionListener(this);
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            Destination destination = session.createQueue("TEST.FOO");
            MessageConsumer consumer = session.createConsumer(destination);
            Message message = consumer.receive(1000);
            if (message instanceof TextMessage) {
                TextMessage textMessage = (TextMessage) message;
                String text = textMessage.getText();
                System.out.println("*****Received: " + text);
            } else {
                System.out.println("*****Received obj: " + message);
            }
            consumer.close();
            session.close();
            connection.close();
        } catch (Exception e) {
            System.out.println("Caught: " + e);
            e.printStackTrace();
        }
    }
main方法只是在一个线程中启动其中的每一个,以开始生成/接收消息

…但我在每个线程的开头都遇到了以下问题:

2013-01-24 07:54:31,271 INFO  [org.apache.activemq.broker.BrokerService] Using Persistence Adapter: AMQPersistenceAdapter(activemq-data/localhost)
2013-01-24 07:54:31,281 INFO  [org.apache.activemq.store.amq.AMQPersistenceAdapter] AMQStore starting using directory: activemq-data/localhost
2013-01-24 07:54:31,302 INFO  [org.apache.activemq.kaha.impl.KahaStore] Kaha Store using data directory activemq-data/localhost/kr-store/state
2013-01-24 07:54:31,339 INFO  [org.apache.activemq.store.amq.AMQPersistenceAdapter] Active data files: []
2013-01-24 07:54:31,445 DEBUG [org.apache.activemq.broker.jmx.ManagementContext] Probably not using JRE 1.4: mx4j.tools.naming.NamingService
2013-01-24 07:54:31,450 DEBUG [org.apache.activemq.broker.jmx.ManagementContext] Failed to create local registry
    java.rmi.server.ExportException: internal error: ObjID already in use
    at sun.rmi.transport.ObjectTable.putTarget(ObjectTable.java:186)
    at sun.rmi.transport.Transport.exportObject(Transport.java:92)
    at sun.rmi.transport.tcp.TCPTransport.exportObject(TCPTransport.java:247)
    at sun.rmi.transport.tcp.TCPEndpoint.exportObject(TCPEndpoint.java:411)
    at sun.rmi.transport.LiveRef.exportObject(LiveRef.java:147)
        <snip....>

您可以通过多种方式将代理嵌入到代码中,其中大部分都有文档记录。您可能想尝试升级您的版本,因为您正在使用的似乎非常旧,因为它默认为现在已弃用的AMQ存储,而不是较新的KahaDB存储。您可能会遇到问题,因为客户端线程之间存在竞争,因为它们使用不同的连接工厂,这些连接工厂可能会在VM代理中竞争创建。如果在producer上设置create=false选项并确保consumer线程在此之后启动,则可以解决该问题,或者您可以提前创建VM代理,并将create=false添加到两个线程,这可能会解决问题

BrokerService broker = new BrokerService();
// configure the broker
broker.setBrokerName("localhost");
broker.setUseJmx(false);
broker.start();
然后在客户端代码中,只需通过此连接工厂配置进行连接

ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory("vm://localhost?create=false");

当我运行您的代码时,出现以下异常:

javax.jms.JMSException: Could not connect to broker URL: tcp://localhost. 
Reason java.lang.IllegalArgumentException: port out of range:-1
您的代理正在运行并侦听端口61616,因此任何尝试连接到代理的客户端都需要在其URL中包含该端口

客户端代码尝试连接到localhost,但没有提到它必须连接的端口。 生产者代码和消费者代码都需要固定

ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost");


修复端口后,我可以运行您的代码。

您应该包含所有代理创建代码,以便我们可以查看您配置的所有代码。如果不需要,可以通过broker.setUseJmx(false)禁用JMX;为了澄清,显示的消息为调试级别。这不一定是错误。它可能只是提供信息。您在实际生成/使用邮件时是否遇到错误?这个问题在这一点上不清楚。我已经完全重新表述了这个问题。基本上,我要问三个子问题。(1) 异常(2)丢失消息和(3)持久性。感谢您查看我的问题。看起来您正在使用非常旧的ActiveMQ版本作为AMQ持久性适配器的默认版本,建议您切换到版本5.8.0。您希望在服务器内部运行嵌入式代理(即ActiveMQ本身),还是只运行JMS生产者/消费者?在前一种情况下,请同时发布您如何尝试运行该代理的详细信息。谢谢,我有这样的信息。不过,我仍然担心上述例外情况。您知道是否可以安全地忽略它吗?异常似乎告诉您,客户端连接失败,因为您在客户端仍处于连接状态时关闭了代理。如果你关闭应用程序,这不是一个大问题。看起来您的客户端在其连接工厂中使用的是TCP而不是VM,但问题并不完全清楚。是的。。。这确实是问题所在,可以安全地忽略例外情况。为了避免这种情况,需要在服务器(包括代理)之前关闭客户端。谢谢Satish。我能让它工作。抱歉,我应该结束这个问题。
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost");
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");