CometD + Java + jQuery: слишком много публикаций за один вызов

Здравствуйте, у меня возникла следующая проблема с использованием cometd + jquery + java, которая проводит некоторое тестирование при передаче сообщения.

Это мой web.xml, я использую реализацию аннотаций cometd:

<!-- Cometd Servlet -->
<servlet>
    <servlet-name>cometd</servlet-name>
    <servlet-class>org.cometd.java.annotation.AnnotationCometdServlet</servlet-class>
    <init-param>
        <param-name>timeout</param-name>
        <param-value>60000</param-value>
    </init-param>
    <init-param>
        <param-name>logLevel</param-name>
        <param-value>3</param-value>
    </init-param>
    <init-param>
        <param-name>services</param-name>
        <param-value>com.api.services.UserStatusService</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    <async-supported>true</async-supported>
</servlet>
<servlet-mapping>
    <servlet-name>cometd</servlet-name>
    <url-pattern>/do/cometd/*</url-pattern>
</servlet-mapping>

Это сервис, который я зарегистрировал:

package com.api.services;

import java.util.HashMap;

import javax.inject.Inject;

import org.cometd.bayeux.Message;
import org.cometd.bayeux.client.ClientSession;
import org.cometd.bayeux.client.ClientSessionChannel;
import org.cometd.bayeux.server.BayeuxServer;
import org.cometd.java.annotation.Service;
import org.cometd.java.annotation.Session;
import org.cometd.java.annotation.Subscription;

@Service
public class UserStatusService
{
    @Inject
    private BayeuxServer bayeux;
    @Session
    private ClientSession bayeuxClient;

    @Subscription("/userStatus")
    public void userStatus (Message message)
    {
        HashMap<String, String> mapa = new HashMap<String,String>();
        String channel = message.getChannel();
        System.out.println("*** The Channel is "+channel+" ***");
        ClientSessionChannel chann = bayeuxClient.getChannel(channel);
        mapa.put("canal", channel);
        mapa.put("mensaje", "Hola Wi!!");
        mapa.put("ServChan", bayeux.getChannels().get(0).toString());
        chann.publish(mapa);
    }
}

И это код JS jQuery, который я использую для подписки и публикации (является частью более крупного объекта, поэтому я просто вставляю основное, связанное с этим):

     /** On document ready i call this one **/
     initBroad:function(){
    $.cometd.unregisterTransport('websocket');
    $.cometd.init('http://localhost/MyApp/do/cometd');
    console.log("Set cometd initialization");
    main.broadListener();
},
count:0,
subscription:null,
refresh:function(){
    this.appUnsubscribe();
    this.appSubscribe();
},
appUnsubscribe:function(){
    if (this.subscription) 
        $.cometd.unsubscribe(this.subscription);
    this.subscription = null;
},
appSubscribe:function(){
    func = function(msg){
                    /** I had to do this in order to avoid ALL the 500 times it does it :S **/
        if(main.count < 1){
            console.log(main.count + ": " +  msg.data.mensaje);
        }
        main.count++;
    };
    this.subscription = $.cometd.subscribe("/userStatus",func);
},
broadListener:function(){
    console.log("Set the broadListener");
    main.refresh();
},
publishBroad:function(){
    main.refresh();
    $.cometd.publish('/userStatus', {mensaje:"Hola"});
},

Что ж, после попытки запустить метод publishBroad через консоль, он действительно запускается, но 450-500 раз НА СЕРВЕРЕ одним кликом/запросом (да, это всего лишь один запрос из браузера на java-сервер, 450-500 раз повторяются только на стороне сервера и доходят до браузера в ответ столько раз)!!

Что я сделал не так? Я использую последние версии cometd.js и jquery.cometd.js с официального сайта cometd.

Кроме того, когда я проверяю это в консоли (я использую JBoss AS7), я оставил несколько выходных строк журнала, чтобы увидеть, вошел ли мой вызов в метод ( Sys out println, который говорит, что Channel is:. и он также показывает, что строка журнала 450 -500 раз в консоли JBoss!

Может ли кто-нибудь помочь мне исправить это??

Спасибо!!


person Adrian E. Labastida Cañizares    schedule 16.02.2012    source источник
comment
Не уверен, что не так, хотя я заметил if (this._subscription) $.cometd.unsubscribe(this.subscription); this.subscription = null; я думаю, что у вас есть лишнее подчеркивание   -  person Gabo Esquivel    schedule 16.02.2012
comment
Спасибо, я исправил эту строку, но у меня все еще есть проблема: с одним вызовом метода публикации js cometd я получаю вызов службы на сервере около 500 раз :(   -  person Adrian E. Labastida Cañizares    schedule 17.02.2012


Ответы (1)


Ваша проблема в том, что вы используете ClientSession в своей службе.

Если в вашем сервисе вы просто хотите ответить отправителю, то сделайте так:

@Service
public class UserStatusService
{
    @Session
    private LocalSession session;

    @Subscribe("/userStatus")
    public void userStatus(ServerSession remoteClient, ServerMessage message)
    {
        Map<String, String> map = new HashMap<String,String>();
        map.put("mensaje", "Hola Wi!!");
        remoteClient.deliver(session, message.getChannel(), map, null);
    }
}

Пожалуйста, обратитесь к понятиям CometD, чтобы понять разницу между ClientSession, ServerSession и LocalSession, и к справочнику по аннотированным службам.

Причина петли, которую вы заметили (1 запрос вызвал выполнение службы более 500 раз), заключается в том, что вы повторно транслируете на тот же канал в последней строке, если ваша служба.

person sbordet    schedule 17.02.2012
comment
Спасибо, я попробую это, я не очень хорошо понял концепции из документации кометда даже после различных прочтений и, как вы видите, запутался, я дам вам знать :) - person Adrian E. Labastida Cañizares; 17.02.2012
comment
Кстати, теперь я вспомнил, идея состоит в том, чтобы отправить уведомление всем подпискам на этот канал, поэтому я не использовал метод remoteClient.deliver, и я думал, что способ добраться до них был с помощью метода публикации, я должен прочитайте документы внимательнее и посмотрите, что происходит - person Adrian E. Labastida Cañizares; 17.02.2012