ActiveMQ и встроенный брокер

EDIT: перефразировал вопрос:

Я хочу использовать ActiveMQ в качестве мессенджера между моим сервером и клиентскими приложениями.

Я пытаюсь настроить встроенный брокер (т. е. не отдельный процесс) на сервере для обработки созданных сообщений для моих клиентов. Эта очередь сохраняется.

инициализация брокера следующим образом:

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();
        }
    }

основной метод просто запускает каждый из них в потоке, чтобы начать создавать / получать сообщения.

...но я сталкиваюсь со следующим с началом каждого потока:

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....>

похоже, что сообщения производятся и потребляются успешно (другие проблемы, о которых я ранее писал, были решены), но вышеупомянутое исключение беспокоит меня.

EDIT: во время выключения брокера меня также приветствуют следующие:

2013-01-25 08:40:17,486 DEBUG [org.apache.activemq.transport.failover.FailoverTransport] Transport failed with the following exception:
    java.io.EOFException
    at java.io.DataInputStream.readInt(DataInputStream.java:392)
    at org.apache.activemq.openwire.OpenWireFormat.unmarshal(OpenWireFormat.java:269)
    at org.apache.activemq.transport.tcp.TcpTransport.readCommand(TcpTransport.java:210)
    at org.apache.activemq.transport.tcp.TcpTransport.doRun(TcpTransport.java:202)
    at org.apache.activemq.transport.tcp.TcpTransport.run(TcpTransport.java:185)
    at java.lang.Thread.run(Thread.java:722)

2 ответов


вы можете встроить брокера в свой код несколькими способами, многие из которых документированы здесь. Вы можете попробовать обновить версию, так как то, что вы используете, кажется довольно старым, поскольку по умолчанию теперь устаревший магазин AMQ вместо нового магазина KahaDB. У вас могут быть проблемы из-за гонки между потоками клиента, поскольку они используют различные фабрики соединений, которые могут участвовать в гонке для создания в брокерах VM. Если вы установите параметр create=false на производитель и убедитесь, что поток потребителя запускается после этого, может решить проблему, или вы можете создать брокер 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");

до

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

после исправления порта я смог запустить ваш код.