Полный код доступен на 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 — тогда вы, вероятно, делаете кучу других преобразований и обработки в промежутке между получением и публикацией данных.)