В предыдущем посте рассматривался пример внедрения HornetQ сервера в приложение. Попробуем немного усовершенствовать его, переложив часть работы на Spring.
Необходимо подключить к проекту spring-jms.jar, после чего добавить немного кода в конфиг Spring
Это наш встроенный HornetQ сервер, он будет стартовать и останавливаться автоматически при поднятии контекста.
<bean class="org.hornetq.jms.server.embedded.EmbeddedJMS"
destroy-method="stop"
id="jmsServer"
init-method="start"/>
Локатор ConnecitonFactory. Этот класс возвращает экземпляр ConnecitonFactory. Обычно ConnecitonFactory биндится на JNDI, но не в нашем случае, так что требуется специальный класс для того, чтобы получить ее.
<bean class="example.jms.JmsConnecitonFactoryLocator"
depends-on="jmsServer"
factory-method="lookupConnectionFactory"
id="jmsConnectionFactory">
<constructor-arg= name="server" ref="jmsServer" />
</bean>
Это стандартный JMSTemplate, с его помошью мы будет отсылать сообщения в очередь
<bean class="org.springframework.jms.core.JmsTemplate"
depends-on="jmsServer"
id="jmsQueueTemplate">
<property name="connectionFactory">
<ref bean="jmsConnectionFactory"/>
</property>
</bean>
JmsQueueLocator - класс-фабрика для получения экземпляра очереди. Необходим для того, чтобы организовать приемник сообщений.
<bean class="example.jms.JmsQueueLocator"
depends-on="jmsServer"
factory-method="lookupQueue"
id="paymentQueue">
<constructor-arg name="server" ref="jmsServer" />
<constructor-arg name="queueName" value="queue/paymentQueue" />
</bean>
Собственно класс, отвественный за получение сообщений. Поддерживает несколько конкурентных получателей.Обратите внимание на ref="transactionPusher". Данный бин определяется в коде посредством аннотации @Component(value = "transactionPusher")
<bean id="jmsContainerPayment"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsConnectionFactory"/>
<property name="destination" ref="paymentQueue"/>
<property name="messageListener" ref="transactionPusher" />
<property name="concurrentConsumers" value="5"/>
</bean>
Теперь код:
Класс-фабрика для получения соединения с нашим встроенным JMS сервером
public class JmsConnecitonFactoryLocator {
private static final Logger logger = LoggerFactory.getLogger(JmsConnecitonFactoryLocator.class);
public static HornetQJMSConnectionFactory lookupConnectionFactory(EmbeddedJMS server){
HornetQJMSConnectionFactory cf = (HornetQJMSConnectionFactory) server.lookup("ConnectionFactory");
if(cf == null){
logger.error("connection factory is null");
}else{
logger.info("connection factory is not null");
}
return cf;
}
}
Класс-фабрика для получения экземпляра очереди
public class JmsQueueLocator {
public static Queue lookupQueue(EmbeddedJMS server, String queueName){
return (Queue) server.lookup(queueName);
}
}
Класс - приемник сообщений
@Component(value = "transactionPusher")
public class TransactionPusher implements MessageListener {
private static final Logger logger = LoggerFactory.getLogger(TransactionPusher.class);
@Override
public void onMessage(Message message) {
try{
TextMessage m = (TextMessage)message;
m.acknowledge(); // говорим, что успешно приняли сообщение.
// сделать что-то полезное
} catch (JMSException e) {
logger.error("JMS exceptoin: ", e);
}
}
}
Пример использования JMSTemplate для отсылки сообщений:
public void addPaymentToQueue(final Transaction t) throws JMSException {
jmsTemplate.send(paymentQueue, new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
TextMessage msg = session.createTextMessage();
msg.setText(String.valueOf(t.getId()));
return msg;
}
});
}
Как можно заметить, Spring берет на себя значительную часть работы по организации рутинных операций, позволяя сосредоточиться на программировании бизнес логики приема и отправки сообщений. Класс DefaultMessageListenerContainer позволяет настраивать количество конкурентных потребителей, а также динамически увеличивать количество потребителей при увеличении нагрузки.
Комментариев нет:
Отправить комментарий