Полный код доступен на GitHub
Весь код Java для проекта доступен на Github — требуется Maven для запуска. Смотрите README для более подробной информации —
ссылка здесь .
Ключевые технические игроки
Демонстрация демонстрирует гармоничное взаимодействие этих различных частей набора:
- CometD Bayeux Ajax Push — технология push-взаимодействия между сервером Camel и веб-браузером [ http://cometd.org/ ]
- Apache Camel — инфраструктура корпоративной интеграции — предоставляет канал производителя корпоративной маршрутизации и CometD [ http://camel.apache.org/ ]
- Apache ActiveMQ — брокер обмена сообщениями JMS [ http://activemq.apache.org/ ]
- Плагин Apache Camel CometD — плагин CometD для Camel [ http://camel.apache.org/cometd.html ]
- И обычные подозреваемые — Java, Spring, Maven, Git
Какой сценарий?
- Представьте себе сложную корпоративную инфраструктуру, в которой используется множество различных систем, серверов и технологий, и между ними передаются данные.
- Обычно в игре будет какая-то система обмена сообщениями — маршрутизация и трансформация различных потоков сообщений. В нашем примере мы используем ApacheMQ в качестве сервера обмена сообщениями.
- Конечные точки некоторых из этих потоков могут отправлять данные нескольким клиентам. Один из способов сделать это — направить сообщения в тему, и многие клиенты подписались на эту тему — это просто для клиентов Java, но не так просто, если клиенты являются браузерами.
- Как правило, браузерные клиенты должны использовать метод опроса вручную, чтобы проверить наличие новых данных.
- Использование CometD — браузер может использовать некоторый javascript для подписки на канал CometD, сохраняя открытое долго работающее соединение — и конечная точка этого канала может передавать данные напрямую всем своим подписчикам. Удобно, Apache Camel поставляется с плагином CometD, который может обрабатывать все это на стороне сервера для нас.
CometD и Camel Demo
Демонстрация показывает сообщения HTML, отправляемые в очередь JMS ActiveMQ, откуда они отбираются Camel и затем направляются в конечную точку канала CometD.
HTML-страница потребляет сообщения из канала CometD — и по мере их поступления добавляет их в список на веб-странице. Пример HTML-страницы показан ниже (я добавил JQuery, чтобы сначала перетаскивать изображения в красный цвет, а затем постепенно затушевывать их — только для того, чтобы это было очевидно по мере поступления новых сообщений).
Сообщения являются простыми и генерируются автоматически из клиентского приложения Java, которое отправляет их в ActiveMQ с помощью Spring JMSTemplate.
Этот поток показан на диаграмме ниже. Все три составные части могут быть запущены из одного проекта (но они должны быть запущены в указанной последовательности — сначала ActiveMQ / Camel-сервер, затем веб-браузер, затем Java-клиент)
Запуск демо
- Посмотрите файл README в Github для получения полной информации о том, как запустить демонстрацию (только помните, что они должны быть запущены в последовательности выше — сервер ActiveMQ \ Camel должен быть запущен первым, чтобы браузер использовал канал cometd и клиент отправил JMS сообщение)
Верблюжий путь
- Свойства устанавливаются в application.properties
broker.url=tcp://localhost:61616 broker.queue=corsoft.BroadcastMessageQueue cometd.channel=cometd://0.0.0.0:9099/broadcastMessageChannel
- The Camel Route — прослушивает очередь и выводит на канал CometD
<!-- Server Camel Context (running inside ActiveMQ) --> <camelContext xmlns="http://camel.apache.org/schema/spring"> <!-- Load properties to Camel Context --> <propertyPlaceholder id="properties" location="application.properties" /> <!-- Camel Broadcast Message Route --> <route id="processIncomingFilesRoute" trace="true" xmlns="http://camel.apache.org/schema/spring"> <!-- Listen on this Queue for incoming Messages --> <from uri="activemq://queue:{{broker.queue}}" /> <!-- Log to console --> <log message="Incoming Message - distribute via Cometd" loggingLevel="INFO" /> <!-- Creates a Cometd channel endpoint Broadcast to all Cometd registered subscribers --> <to uri="{{cometd.channel}}" /> </route> </camelContext>
Потребитель Javascript
google.load("jquery", "1");
/**
* Callback function - Cometd consumer.
*/
google.setOnLoadCallback(function() {
$.getScript("http://jquerycomet.googlecode.com/svn/trunk/jquery.comet.js", function(){
console.log("done loading js");
$.comet.init("http://localhost:9099/cometd");
$.comet.subscribe("/broadcastMessageChannel", broadcastListener);
});
});
/**
* Listener function called on receipt of broadcast message.
*/
function broadcastListener(msg) {
console.log("received broadcast: " + msg + ", " + msg.data);
$('<li>').html(msg.data).prependTo('#contentList').animate({color: "#000000"}, 6000);
$('html, body').animate({ scrollTop: 0 }, 0);
}
Диспетчер сообщений клиента Java
package com.cor.demo;
import java.io.Serializable;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Component;
/**
* Delegate for sending messages to ActiveMQ Broker via the Spring JMSTemplate.
*/
@Component
public class MessageDispatcher {
/** Logger. */
private static Logger LOG = LoggerFactory.getLogger(MessageDispatcher.class);
/** JMS Template. */
@Autowired
protected JmsTemplate jmsTemplate;
/**
* Send the objectMessage to the Broker and Queue defined in application.properties.
* @param objectMessage Object Message
*/
public void sendMessageObject(final Serializable objectMessage) {
LOG.info("Sending message " + objectMessage);
jmsTemplate.send(new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
ObjectMessage message = session.createObjectMessage(objectMessage);
return message;
}
});
LOG.info("Message Sent!");
}
}
Будущие расширения
- Очевидно, что это довольно простая демонстрация — в реальной ситуации вы можете не захотеть отправлять необработанный HTML по каналу. Лучшим решением будет JSON, позволяющий клиенту извлекать и форматировать, как он хочет.
- (И если вы используете Camel — тогда вы, вероятно, делаете кучу других преобразований и обработки в промежутке между получением и публикацией данных.)

