Как подключиться к RabbitMQ с помощью клиента RabbitMQ JMS из существующего приложения JMS?

У меня есть общее автономное приложение JMS, которое работает со следующими поставщиками JMS WebSphere, HornetQ и ActiveMq. Я передаю контекст.INITIAL_CONTEXT_FACTORY и контекст.PROVIDER_URL в качестве параметров для моего приложения и создать контекст именования из них, делая что-то вроде этого

Properties environmentParameters = new Properties();
environmentParameters.put(Context.INITIAL_CONTEXT_FACTORY, property.context);
environmentParameters.put(Context.PROVIDER_URL, property.provider);
namingContext = new InitialContext(environmentParameters);

и используйте этот контекст для поиска объектов.

Я понимаю, что RabbitMQ не является поставщиком JMS, поэтому у него нет класса InitialContext или URL-адреса поставщика, но он предоставляет клиент JMS, который является абстракцией его клиента Java, соответствующего спецификации JMS. Клиент JMS RabbitMQ документация имеет пример определения объектов в JNDI в качестве конфигурации ресурса как части веб-приложения, но я совершенно не мог понять, как сделать что-то подобное для моего автономного приложения, которое создает контекст именования на основе поставщика JNDI, используя зависимости клиента JMS или создать InitialContext из доступных зависимостей.

Так может кто-нибудь пролить свет на то, как это можно сделать? Надеюсь, мой вопрос ясен.

3 ответов


для получения JMS работает с RabbitMQ вы должны включить на плагин rabbitmq_jms_topic_exchange.
Вы можете скачать его, следуя инструкциям на этом сайте (вам нужно login):
https://my.vmware.com/web/vmware/details?downloadGroup=VFRMQ_JMS_105&productId=349

  1. после извлечения поместите файл rjms-topic-selector-1.0.5.ez внутри папки $RABBITMQ_SERVER\Плагины.
  2. включить плагин с помощью команды: rabbitmq-plugins enable rabbitmq_jms_topic_exchange
  3. проверьте, работает ли плагин нормально с командой:rabbitmq-plugins list
    List of RabbitMQ plugins
  4. перезагрузите RabbitMQ - я не уверен, что это действительно необходимо, но на всякий случай; -)
  5. в вашем веб-управлении RabbitMQ (http://localhost:15672/#/exchanges) вы можете проверить новый обмен вы имеете доступный: Exchanges of the RabbitMQ
  6. теперь, теоретически: -), вы уже можете подключиться к вашему серверу RabbiMQ, используя стандартный JAVA JMS API.

имейте в виду, что вам придется создать .файл Привязок для того, чтобы JNDI нашел ваши зарегистрированные объекты. Вот пример его содержания:


    ConnectionFactory/ClassName=com.rabbitmq.jms.admin.RMQConnectionFactory
    ConnectionFactory/FactoryName=com.rabbitmq.jms.admin.RMQObjectFactory
    ConnectionFactory/RefAddr/0/Content=jms/ConnectionFactory
    ConnectionFactory/RefAddr/0/Type=name
    ConnectionFactory/RefAddr/0/Encoding=String
    ConnectionFactory/RefAddr/1/Content=javax.jms.ConnectionFactory
    ConnectionFactory/RefAddr/1/Type=type
    ConnectionFactory/RefAddr/1/Encoding=String
    ConnectionFactory/RefAddr/2/Content=com.rabbitmq.jms.admin.RMQObjectFactory
    ConnectionFactory/RefAddr/2/Type=factory
    ConnectionFactory/RefAddr/2/Encoding=String
    # Change this line accordingly if the broker is not at localhost
    ConnectionFactory/RefAddr/3/Content=localhost
    ConnectionFactory/RefAddr/3/Type=host
    ConnectionFactory/RefAddr/3/Encoding=String
    # HELLO Queue 
    HELLO/ClassName=com.rabbitmq.jms.admin.RMQDestination
    HELLO/FactoryName=com.rabbitmq.jms.admin.RMQObjectFactory
    HELLO/RefAddr/0/Content=jms/Queue
    HELLO/RefAddr/0/Type=name
    HELLO/RefAddr/0/Encoding=String
    HELLO/RefAddr/1/Content=javax.jms.Queue
    HELLO/RefAddr/1/Type=type
    HELLO/RefAddr/1/Encoding=String
    HELLO/RefAddr/2/Content=com.rabbitmq.jms.admin.RMQObjectFactory
    HELLO/RefAddr/2/Type=factory
    HELLO/RefAddr/2/Encoding=String
    HELLO/RefAddr/3/Content=HELLO
    HELLO/RefAddr/3/Type=destinationName
    HELLO/RefAddr/3/Encoding=String

и потом... в конечном счете... код:


    Properties environmentParameters = new Properties();
    environmentParameters.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
    environmentParameters.put(Context.PROVIDER_URL, "file:/C:/rabbitmq-bindings");
    namingContext = new InitialContext(environmentParameters);

    ConnectionFactory connFactory = (ConnectionFactory) ctx.lookup("ConnectionFactory");


для людей, которые бьют это исключение

Caused by: javax.naming.NamingException: Unknown class [com.rabbitmq.jms.admin.RMQConnectionFactory]

даже после ответа @Ualter-младшего из-за некорректной записи .файл привязки.

я исправил следующие 2 строки .файл Привязок

ConnectionFactory/ClassName=com.rabbitmq.jms.admin.RMQConnectionFactory --->
ConnectionFactory/ClassName=javax.jms.ConnectionFactory

и

YourQueueName/ClassName=com.rabbitmq.jms.admin.RMQDestination --->
StriimQueue/ClassName=javax.jms.Queue

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

      /*
     * Valid class names are:
     * javax.jms.ConnectionFactory
     * javax.jms.QueueConnectionFactory
     * javax.jms.TopicConnectionFactory
     * javax.jms.Topic
     * javax.jms.Queue
     *
     */

исправление этих записей позволит существующие / новые приложения JMS для работы с RabbitMQ.


мы можем создать .файл Привязок для RabbitMQ, используя ниже java-код:

import java.util.Properties;
import javax.jms.ConnectionFactory;
import javax.jms.Queue;
import javax.jms.Topic;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.Reference;
import javax.naming.StringRefAddr;

Properties env = new Properties();
    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
    env.put(Context.PROVIDER_URL, "file:bindings");
    Context ctx = new InitialContext(env);

    Reference connectionFactoryRef = new Reference(ConnectionFactory.class.getName(), RMQObjectFactory.class.getName(), null);
    connectionFactoryRef.add(new StringRefAddr("name", "jms/ConnectionFactory"));
    connectionFactoryRef.add(new StringRefAddr("type", ConnectionFactory.class.getName()));
    connectionFactoryRef.add(new StringRefAddr("factory", RMQObjectFactory.class.getName()));
    connectionFactoryRef.add(new StringRefAddr("host", "$JMS_RABBITMQ_HOST$"));
    connectionFactoryRef.add(new StringRefAddr("port", "$JMS_RABBITMQ_PORT$"));
    ctx.rebind("ConnectionFactory", connectionFactoryRef);

    String jndiAppend = "jndi";
    for (int i = 1; i <= 10; i++) {
        String name = String.format("queue%02d", i);
        Reference ref = new Reference(Queue.class.getName(), com.rabbitmq.jms.admin.RMQObjectFactory.class.getName(), null);
        ref.add(new StringRefAddr("name", "jms/Queue"));
        ref.add(new StringRefAddr("type", Queue.class.getName()));
        ref.add(new StringRefAddr("factory", RMQObjectFactory.class.getName()));
        ref.add(new StringRefAddr("destinationName", name));
        ctx.rebind(name+jndiAppend, ref);

        name = String.format("topic%02d", i);
        ref = new Reference(Topic.class.getName(), com.rabbitmq.jms.admin.RMQObjectFactory.class.getName(), null);
        ref.add(new StringRefAddr("name", "jms/Topic"));
        ref.add(new StringRefAddr("type", Topic.class.getName()));
        ref.add(new StringRefAddr("factory", RMQObjectFactory.class.getName()));
        ref.add(new StringRefAddr("destinationName", name));
        ctx.rebind(name+jndiAppend, ref);
    }