Как подключиться к 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
- после извлечения поместите файл rjms-topic-selector-1.0.5.ez внутри папки $RABBITMQ_SERVER\Плагины.
- включить плагин с помощью команды:
rabbitmq-plugins enable rabbitmq_jms_topic_exchange
- проверьте, работает ли плагин нормально с командой:
rabbitmq-plugins list
- перезагрузите RabbitMQ - я не уверен, что это действительно необходимо, но на всякий случай; -)
- в вашем веб-управлении RabbitMQ (http://localhost:15672/#/exchanges) вы можете проверить новый обмен вы имеете доступный:
- теперь, теоретически: -), вы уже можете подключиться к вашему серверу 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);
}