У современных пользователей востребованы быстрые, динамичные приложения, доступные через Интернет. В этом цикле статей показано, как разработать событийно-управляемое Web-приложение с использованием методов Reverse Ajax. Часть 1 знакомит читателя с методами Reverse Ajax - опросами, потоками, Comet и ждущим опросом. Из нее видно, что Comet с использованием ждущих HTTP-опросов ― это лучший способ надежной реализации Reverse Ajax, поскольку он поддерживается во всех современных браузерах. В части 2 показано, как реализовать Reverse Ajax с помощью WebSockets. Примеры кода помогают проиллюстрировать WebSockets, FlashSockets, ограничения на стороне сервера, сервисы, ограниченные одним запросом (request-scoped), и приостановку долгоживущих запросов.
В этой статье мы углубимся в детали использования Comet и WebSockets в Web-приложении для различных Web-контейнеров и API (Servlet 3.0 и Jetty Continuations). Вы научитесь прозрачно использовать Comet и WebSockets с помощью библиотек абстрагирования, таких как Socket.IO. Библиотека Socket.IO применяет методы обнаружения функций, чтобы решить, будет ли соединение установлено посредством WebSocket, ждущего опроса AJAX, Flash и т.п.
Загрузите исходный код примеров для этой статьи.
Чтобы извлечь максимальную пользу из этой статьи, в идеале нужно знать JavaScript и Java. Пример, создаваемый в этой статье, построен с помощью Google Guice - среды внедрения зависимостей, написанной на Java. Для работы с этой статьей требуется знакомство с идеями сред внедрения зависимостей, таких как Guice, Spring или Pico.
Для запуска примера из этой статьи также понадобится последняя версия Maven и JDK (см. раздел Ресурсы).
Серверные решения для Comet и WebSocket
В первой части мы рассказали, что для Comet (ждущий опрос или потоковая передача) требуется, чтобы сервер мог приостанавливать запрос и возобновлять или завершать его впоследствии, возможно, через длительное время. В части 2 говорится о том, как серверы должны использовать функции неблокирующего ввода/вывода для обработки большого количества соединений, а также о том, что для обслуживания запросов они используют только потоки (модель "поток на запрос"). Вы также узнали, что способ использования WebSocket зависит от сервера и не все серверы поддерживают WebSockets.
В этом разделе показано, как использовать Comet и WebSockets, если это возможно, на Web-серверах Jetty, Tomcat и Grizzly. Исходный код для этой статьи содержит Web-приложение для Jetty и Tomcat. В этом же разделе обсуждаются поддерживаемые API для следующих серверов приложений: JBoss, Glassfish и WebSphere.
Jetty – это Web-сервер, поддерживающий спецификации Java Servlet 3.0, WebSockets и многие другие спецификации интеграции. Сервер Jetty:
- отличается мощностью и гибкостью;
- легко встраивается;
- поддерживает виртуальные хосты, кластеризацию сеансов, а также множество функций, которые можно легко настроить с помощью Java- или XML-кода;
- используется для в службеы хостинга Google App Engine.
Проектом Jetty управляет Eclipse Foundation.
Начиная с версии 6, в Jetty входит асинхронный API Jetty Continuations, который позволяет приостанавливать запросы и возобновлять их через некоторое время. В таблице 1 показана карта поддержки спецификаций и API для основных семейств версий Jetty.
Таблица 1. Версии и поддержка Jetty
| Поддерживает | Jetty 6 | Jetty 7 | Jetty 8 |
|---|---|---|---|
| Неблокирующий ввод/вывод | X | X | X |
| Servlet 2.5 | X | X | X |
| Servlet 3.0 | X | X | |
| Jetty Continuations (Comet) | X | X | X |
| WebSockets | X | X |
Для реализации Reverse Ajax с помощью Comet можно использовать API Continuation из Jetty, как показано в листинге 1.
Листинг 1. API Jetty Continuation для Comet
// Приостановка запроса от метода сервлета (get, post, ...):
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
Continuation continuation = ContinuationSupport.getContinuation(req);
// дополнительное задание тайм-аута во избежание слишком долгого ожидания запроса
continuation.setTimeout(0);
// приостанавливает запрос
continuation.suspend();
// затем сохраняет ссылку для будущего использования из другого потока
continuations.offer(continuation);
}
// Затем, из другого потока, который хочет отправить событие клиенту:
while (!continuations.isEmpty()) {
Continuation continuation = continuations.poll();
HttpServletResponse response =
(HttpServletResponse) continuation.getServletResponse();
// запись в ответ
continuation.complete();
}
|
Полное Web-приложение содержится в исходном коде, который прилагается к статье. Jetty Continuations находится в JAR-архиве. Этот JAR-файл нужно поместить в папку WEB-INF/lib Web-приложения, чтобы можно было использовать возможности Comet из Jetty. Jetty Continuations работает на Jetty 6, 7 и 8.
Начиная с Jetty 7 также имеется доступ к функции WebSockets. Чтобы получить доступ к API WebSocket из Jetty, поместите JAR-файл WebSocket из Jetty в папку WEB-INF/lib своего Web-приложения, как показано в листинге 2.
Листинг 2. API WebSocket из Jetty
// Реализация doWebSocketConnect и возврат реализации WebSocket:
public final class ReverseAjaxServlet extends WebSocketServlet {
@Override
protected WebSocket doWebSocketConnect(HttpServletRequest request,
String protocol) {
return [...]
}
}
// Пример реализации WebSocket:
class Endpoint implements WebSocket {
Outbound outbound;
public void onConnect(Outbound outbound) {
this.outbound = outbound;
}
public void onMessage(byte opcode, String data) {
outbound.sendMessage("Echo: " + data);
if("close".equals(data))
outbound.disconnect();
}
public void onFragment(boolean more, byte opcode,
byte[] data, int offset, int length) {
}
public void onMessage(byte opcode, byte[] data,
int offset, int length) {
onMessage(opcode, new String(data, offset, length));
}
public void onDisconnect() {
outbound = null;
}
}
|
В папке jetty-websocket загружаемого исходного кода есть образец чата, который демонстрирует, как использовать API WebSocket из Jetty.
Tomcat, пожалуй, - самый популярный Web-сервер. Он применяется на протяжении многих лет и включен в качестве Web-контейнера в самые ранние версии сервера приложений JBoss. Tomcat используется и в качестве эталонной реализации спецификации сервлетов. В Servlet API 2.5 он исключен, так как люди стали искать альтернативы на основе неблокирующего ввода/вывода (такие как Jetty). В таблице 2 указаны поддерживаемые спецификации и API двух последних семейств версий Tomcat.
Таблица 2. Поддержка Tomcat
| Поддерживает | Tomcat 6 | Tomcat 7 |
|---|---|---|
| Неблокирующий ввод/вывод | X | X |
| Servlet 2.5 | X | X |
| Servlet 3.0 | X | |
| Advanced I/O (Comet) | X | X |
| WebSockets |
Как видно из таблицы 2, Tomcat не поддерживает WebSockets; однако в нем есть эквивалент Continuations из Jetty под названием Advanced I/O для поддержки Comet. Advanced I/O ― это скорее низкоуровневая оболочка для NIO, чем хороший API для облегчения использования Comet. Этот API плохо документирован, и примеров приложений, использующих его, немного. В листинге 3 показан пример сервлета для приостановки и возобновления запросов в Web-приложении чата. Полное Web-приложение находится в исходном коде, прилагаемом к этой статье.
Листинг 3. API Tomcat для Comet
public final class ChatServlet extends HttpServlet
implements CometProcessor {
private final BlockingQueue<CometEvent> events =
new LinkedBlockingQueue<CometEvent>();
public void event(CometEvent evt)
throws IOException, ServletException {
HttpServletRequest request = evt.getHttpServletRequest();
String user =
(String) request.getSession().getAttribute("user");
switch (evt.getEventType()) {
case BEGIN: {
if ("GET".equals(request.getMethod())) {
evt.setTimeout(Integer.MAX_VALUE);
events.offer(evt);
} else {
String message = request.getParameter("message");
if ("/disconnect".equals(message)) {
broadcast(user + " disconnected");
request.getSession().removeAttribute("user");
events.remove(evt);
} else if (message != null) {
broadcast("[" + user + "]" + message);
}
evt.close();
}
}
}
}
void broadcast(String message) throws IOException {
Queue<CometEvent> q = new LinkedList<CometEvent>();
events.drainTo(q);
while (!q.isEmpty()) {
CometEvent event = q.poll();
HttpServletResponse resp = event.getHttpServletResponse();
resp.setStatus(HttpServletResponse.SC_OK);
resp.setContentType("text/html");
resp.getWriter().write(message);
event.close();
}
}
}
|
В Tomcat асинхронный сервлет должен реализовывать CometProcessor. Для асинхронных сервлетов Tomcat не вызывает стандартные HTTP-методы (doGet, doPost и т.п.). Вместо этого событие передается в метод event (CometdEvent). Когда запрос приходит впервые, пример проверяет, является ли он запросом GET, чтобы приостановить его. evt.close() не вызывается. Если это POST, то это означает, что пользователь отправил сообщение; в этом случае запрос пересылается другому CometEvent, и для завершения запроса post вызывается метод evt.close(). На стороне клиента программа рассылки выполняет все запросы ждущего опроса для завершения отправленного сообщения, а также немедленно направляет новый запрос ждущего опроса для приема следующих событий.
Grizzly – это не Web-контейнер, а скорее инфраструктура NIO, которая помогает разработчикам создавать масштабируемые приложения. Она разработана в рамках проекта GlassFish, но также может использоваться отдельно или как встроенный компонент. Grizzly содержит компоненты для работы в качестве HTTP/HTTPS сервера и для Bayeux Protocol, Servlet, HttpService OSGi, Comet и др. Grizzly поддерживает WebSockets и используется в Glassfish для обеспечения поддержки Comet и WebSocket.
Glassfish, сервер приложений Oracle, представляет собой эталонную реализацию спецификации J2EE 6.Glassfish – это полный комплекс, такой же, как WebSphere и JBoss, с использованием Grizzly для поддержки NIO, WebSocket и Comet. Модульная архитектура, основанная на OSGi, делает его чрезвычайно гибким с точки зрения замены компонентов. В таблице 3 показана поддержка Glassfish для Comet и WebSockets.
Таблица 3. Поддержка Glassfish
| Поддерживает | Glassfish 2 | Glassfish 3 |
|---|---|---|
| Неблокирующий ввод/вывод | X | X |
| Servlet 2.5 | X | X |
| Servlet 3.0 | X | |
| Comet | X | X |
| WebSockets | X |
Использовать Grizzly нетривиально, так как эта инфраструктура предназначена для встраивания или непосредственной работы из кода Java. Она широко применяется в качестве платформы для поддержки Comet и WebSockets, которую можно встроить в более крупное приложение, такое как Glassfish, которое обеспечивает развертывание Web-возможностей и спецификации Servlet API.
В разделе Ресурсы приведены ссылки на примеры WebSockets и Comet в Grizzly или GlassFish. Так как Glassfish использует Grizzly, примеры должны работать на обеих платформах. API WebSocket очень похож на API Jetty, но API Comet сложнее.
Jboss - это сервер приложений, построенный на базе Tomcat. Он поддерживает Comet и NIO начиная с версии 5. Jboss 7 все еще находится в стадии разработки, но включен в таблицу 4.
Таблица 4. Поддержка Jboss
| Поддерживает | Jboss 5 | Jboss 6 | Jboss 7 |
|---|---|---|---|
| Неблокирующий ввод/вывод | X | X | X |
| Servlet 2.5 | X | X | X |
| Servlet 3.0 | X | X | |
| Comet | X | X | X |
| WebSockets |
WebSphere – это сервер приложений IBM. Поддержка API Servlet 3 (со стандартизированным асинхронным API для Comet) появилась в версии WebSphere 8 (см. анонс в разделе Ресурсы).
Таблица 5. Поддержка WebSphere
| Поддерживает | WebSphere 8 |
|---|---|
| Неблокирующий ввод/вывод | X |
| Servlet 2.5 | X |
| Servlet 3.0 | X |
| Comet | X |
| WebSockets |
Каждый сервер предлагает свой собственный API для Comet и WebSocket. Легко догадаться, что написать переносимое Web-приложение – дело непростое. Спецификация Servlet 3.0 включает в себя дополнительные методы для приостановки и последующего возобновления запроса, что позволяет всем Web-контейнерам, поддерживающим спецификацию Servlet 3.0, поддерживать запросы ждущего опроса Comet.
Группа разработчиков Jetty предоставляет библиотеку Jetty Continuation, которая не зависит от контейнера Jetty. Библиотека Jetty Continuation достаточно умна, чтобы обнаружить присутствие контейнера или спецификации. При работе на сервере Jetty будет использоваться собственный API Jetty. При работе в контейнере, поддерживающем спецификацию Servlet 3.0, будет использоваться этот общий API. В противном случае используется немасштабируемая реализация.
Что касается WebSockets, то в Java еще нет соответствующего стандарта, и, следовательно, если вы хотите использовать в своем Web-приложении WebSockets, нужно брать API поставщика контейнера.
В таблице 6 приведена сводка технологий, поддерживаемых различными серверами.
Таблица 6. Технологии, поддерживаемые серверами
| Контейнер | Comet | WebSocket |
|---|---|---|
| Jetty 6 | Jetty Continuations | N/A |
| Jetty 7 | Servlet 3.0 Jetty Continuations | Native Jetty API |
| Jetty 8 | Servlet 3.0 Jetty Continuations | Native Jetty API |
| Tomcat 6 | Advanced I/O | N/A |
| Tomcat 7 | Servlet 3.0 Advanced I/O Jetty Continuations | N/A |
| Glassfish 2 | Native Grizzly API | N/A |
| Glassfish 3 | Servlet 3.0 Native Grizzly API Jetty Continuations | Native Grizzly API |
| Jboss 5 | Native Jboss API | N/A |
| Jboss 6 | Servlet 3.0 Native Jboss API Jetty Continuations | N/A |
| Jboss 7 | Servlet 3.0 Native Jboss API Jetty Continuations | N/A |
| WebSphere 8 | Servlet 3.0 Jetty Continuations | N/A |
Очевидного решения для WebSockets, за исключением API контейнера, не существует. Что касается Comet, то каждый контейнер, поддерживающий спецификацию Servlet 3.0, поддерживает и Comet. Преимущество Jetty Continuations в данном случае заключается в наличии поддержки Comet на всех этих контейнерах. Таким образом, некоторые библиотеки Reverse Ajax (которые рассматриваются в следующем разделе и в следующей статье этого цикла), в качестве своего серверного API используют Jetty Continuations.
API Jetty Continuation показан в примере Jetty для этой статьи. Спецификация Servlet 3.0 описана и используются в двух примерах Comet в первой части этой серии.
Учитывая все основные API (Servlet 3.0 и Jetty Continuations), а также всю встроенную поддержку на стороне сервера и два основных способа выполнения Reverse Ajax на стороне клиента (Comet и WebSocket), написать свой собственный код JavaScript и Java для их объединения довольно трудно. Нужно также учесть тайм-ауты, прерывания связи, подтверждение, заявки, буферизацию и т.п.
Остальная часть этой статьи посвящена демонстрации Socket.IO в действии. В части 4 этого цикла рассматриваются Atmosphere и CometD. Все эти три библиотеки представляет собой ПО с открытым исходным кодом, и все они поддерживают Comet и WebSocket на многих серверах.
Socket.IO - это клиентская библиотека JavaScript, которая обеспечивает единый API, подобный WebSocket, для подключиться к удаленному серверу, чтобы асинхронно передавать и принимать сообщения. Предоставляя общий API, Socket.IO поддерживает несколько транспортов: WebSocket, Flash Sockets, ждущий опрос, потоки, постоянные Iframes и опрос JSONP. Socket.IO определяет возможности браузера и пытается выбрать наиболее доступный транспорт. Библиотека Socket.IO совместима практически со всеми браузерами (в том числе старыми версиями, такими как IE 5.5), а также мобильными браузерами. Она также содержит такие функции, как такт, тайм-аут, отключение и обработка ошибок.
На сайте Socket.IO (см. раздел Ресурсы) подробно описано, как работает библиотека и какой браузер и метод Reverse Ajax используется. В принципе Socket.IO использует протокол связи, который позволяет клиентской библиотеке взаимодействовать с конечной точкой на стороне сервера, понимающего протокол Socket.IO. Socket.IO был разработан для Node JS, механизма JavaScript, используемого для создания более быстрых серверов. Многие проекты привнесли поддержку других языков, включая Java.
В листинге 4 приведен пример использования библиотеки JavaScript Socket.IO на стороне клиента. На веб-сайте Socket.IO есть документация и примеры.
Листинг 4. Использование клиентской библиотеки Socket.IO
var socket = new io.Socket(document.domain, {
resource: 'chat'
});
socket.on('connect', function() {
// Socket.IO подсоединен
});
socket.on('disconnect', function(disconnectReason, errorMessage) {
// Socket.IO отсоединен
});
socket.on('message', function(mtype, data, error) {
// Сервер послал событие
});
// Теперь, когда обработчики определены, устанавливается связь:
socket.connect();
|
Чтобы использовать библиотеку Socket.IO JavaScript, нужна соответствующая часть Java - Socket.IO Java (см. раздел Ресурсы). Этот проект изначально создавался группой Apache Wave для добавления в Wave поддержки Reverse Ajax, когда еще не было WebSockets. Проект Socket.IO Java отделился и велся компанией Ovea (специализирующейся на событийной Web-разработке), однако затем компания от него отказались. Разработка серверной части поддержки клиентской библиотеки Socket.IO усложняется наличием нескольких транспортов. В части 4 этого цикла будет показано, что для достижения лучшей масштабируемости и поддержки браузера поддержка многих транспортов в клиентской библиотеке не обязательна, так как достаточно ждущего опроса и WebSockets. При отсутствии WebSockets Socket.IO все же был хорошим выбором.
Для приостановки и возобновления запросов Socket.IO Java использует API Jetty Continuation. Для поддержки WebSockets он использует собственный API Jetty WebSockets. Вы можете определить, какой сервер будет корректно работать с Web-приложением, использующим Socket.IO Java.
В листинге 5 приведен пример использования Socket.IO на сервере. Нужно определить расширение сервлета SocketIOServlet и реализовать метод, который возвращает своего рода представление конечной точки. Сам API очень похож на API WebSockets. Его преимущество заключается в том, что этот API используется на стороне сервера, независимо от транспорта, выбранного на стороне клиента. Socket.IO переводит все виды транспортов в один и тот же API на стороне сервера.
Листинг 5. Библиотека Socket.IO Java, используемая для примера чата - сервлет
public final class ChatServlet extends SocketIOServlet {
private final BlockingQueue<Endpoint> endpoints =
new LinkedBlockingQueue<Endpoint>();
@Override
protected SocketIOInbound doSocketIOConnect
(HttpServletRequest request) {
String user =
(String) request.getSession().getAttribute("user");
return user == null ? null : new Endpoint(this, user, request);
}
void broadcast(String data) {
for (Endpoint endpoint : endpoints) {
endpoint.send(data);
}
}
void add(Endpoint endpoint) {
endpoints.offer(endpoint);
}
void remove(Endpoint endpoint) {
endpoints.remove(endpoint);
}
}
|
В листинге 6 показано, как вернуть конечную точку.
Листинг 6. Использование библиотеки Socket.IO Java для примера чата - конечная точка
class Endpoint implements SocketIOInbound {
[...]
private SocketIOOutbound outbound;
[...]
@Override
public void onConnect(SocketIOOutbound outbound) {
this.outbound = outbound;
servlet.add(this);
servlet.broadcast(user + " connected");
}
@Override
public void onDisconnect(DisconnectReason reason,
String errorMessage) {
outbound = null;
request.getSession().removeAttribute("user");
servlet.remove(this);
servlet.broadcast(user + " disconnected");
}
@Override
public void onMessage(int messageType, String message) {
if ("/disconnect".equals(message)) {
outbound.close();
} else {
servlet.broadcast("[" + user + "] " + message);
}
}
void send(String data) {
try {
if (outbound != null
&& outbound.getConnectionState() == ConnectionState.CONNECTED) {
outbound.sendMessage(data);
}
} catch (IOException e) {
outbound.close();
}
}
}
|
Полный пример Socket.IO содержится в папке socketio исходного кода.
Все Web-контейнеры поддерживают Comet, и почти все поддерживают WebSockets. Даже если спецификации ведут к нескольким разным реализациям, зависящим от платформы, все равно можно разработать Web-приложение с применением Comet с общими API (Servlet 3.0 или Jetty Continuations). Более того, применяя такие библиотеки, как Socket.IO, можно прозрачно использовать всю мощь Comet и WebSockets. Еще две библиотеки, Atmosphere и CometD, будут рассмотрены в следующей статье этого цикла. Все три библиотеки обеспечивают поддержку разных браузеров, открывают фантастические возможности для пользователей и поддерживают обработку ошибок, упрощенные API, тайм-ауты и возобновление соединений.
| Описание | Имя | Размер | Метод загрузки |
|---|---|---|---|
| Исходный код примера для статьи | reverse_ajaxpt3_source.zip | 21 КБ | HTTP |
Научиться
- Оригинал статьи
- Предыдущие статьи этого цикла:
-
JSR 315: спецификация Java Servlet 3.0 - обновление спецификации версии 2.5.
- Анонс IBM WebSphere Application Server V8.0.
- Google AppEngine uses Jetty!: описание настройки Jetty от Google.
- подробнее о Jetty Continuations и ее функциях.
- Пример Glassfish WebSockets с использованием Grizzly.
- WebSphere Application Server: Подробнее о флагманском продукте семейства IBM WebSphere.
-
WebSphere 8 (с поддержкой Comet) позволяет интеллектуально управлять средой приложений и помогает быстрее предоставить пользователям широкие возможности.
-
Socket.IO стирает грани между различными механизмами транспорта, делая приложения реального времени возможными в любом браузере и мобильном устройстве.
- Start using HTML5 WebSockets today (Nettuts+): статья о том, как выполнять WebSocket-сервер в PHP и как построить клиент для отправки и получения сообщений от него по протоколу WebSocket.
- The WebSocket API (W3C, июль 2011 г.): спецификация, определяющая API, который позволяет Web-страницам использовать протокол WebSocket для двусторонней связи с удаленным хостом.
- Подробнее о поддержке асинхронной обработки в Servlet 3.0
- Подробнее о Comet и Java в блоге Филиппа Маккарти: сравнение поточного и неблокирующего ввода/вывода.
-
The Rox Java NIO Tutorial: накопленный автором опыт использования библиотек Java NIO и десятки советов, предложений и предостережений, найденных в Интернете.
- Читайте в Википедии об:
-
Exploring Reverse AJAX: введение в некоторые методы Reverse Ajax.
- Cross-domain communications with JSONP, Part 1: Combine JSONP and jQuery to quickly build powerful mashups (developerWorks, февраль 2009 г.): как сочетать метод скрытого междоменного вызова (JSONP) с гибкой библиотекой JavaScript (JQuery) для создания мощных и на удивление быстрых гибридных приложений.
- Build Ajax applications with Ext JS (developerWorks, июль 2008 г.): обзор концепций объектно-ориентированного JavaScript-программирования, стоящих за Ext JS, и способов применения инфраструктуры Ext JS для элементов пользовательского интерфейса многофункциональных интернет-приложений.
- Compare JavaScript frameworks (developerWorks, февраль 2010 г.): обзор интегрированных сред разработки, которые значительно упрощают разработку на JavaScript.
- Mastering Ajax, Part 2: Make asynchronous requests with JavaScript and Ajax (developerWorks, январь 2006 г.): как использовать Ajax и объект XMLHttpRequest для создания модели запрос/ответ, которая никогда не заставляет пользователя ждать реакции сервера.
- Create Ajax applications for the mobile web (developerWorks, март 2010 г.): как создавать не зависящие от браузера Web-приложения для смартфона с использованием Ajax.
- Where and when to use Ajax in your applications (developerWorks, февраль 2008 г.): как использовать Ajax для совершенствования Web-сайтов, избегая неудобств для пользователей.
- Improve the performance of web 2.0 applications (developerWorks, декабрь 2009 г.): различные механизмы кэширования на стороне браузера.
- Introducing JSON (JSON.org): введение в синтаксис JSON.
Получить продукты и технологии
-
Jetty: Jetty, Web-сервер и контейнер javax.servlet с поддержкой WebSockets.
- Документация Apache Tomcat Advanced I/O: полезные ссылки, руководство пользователя, справочник и инструкции по разработке для Apache Tomcat.
-
Grizzly NIO Framework: воспользуйтесь преимуществами API Java NIO.
-
Пример Comet для Grizzly: узнайте об изменениях, которые нужно внести в существующие приложения, прежде чем создавать новые с нуля.
-
Glassfish Application Server: основной пакет GlassFish Server Open Source Edition.
-
Socket.IO Java: получить оригинальный проект и самый последний вариант Ovea.
- Apache Maven: инструмент для управления проектами разработки программного обеспечения.
Обсудить

Матье Карбу (Mathieu Carbou), Java Web-архитектор и консультант компании Ovea, предоставляет услуги и разрабатывает решения. Он коммиттер и руководитель нескольких проектов по разработке ПО с открытым исходным кодом, докладчик и глава монреальской группы пользователей Java. Матье обладает богатым практическим опытом программирования и специализируется на разработке событийно-управляемых Web-программ для клиентских и серверных систем, а также на решениях для высокомасштабируемых Web-приложений, управляемых событиями и сообщениями. Познакомьтесь с его блогом.