Клиент Cometd javascript не подписывается на канал вещания

Похоже, клиент javascript не может подписаться на широковещательный канал или получить от него сообщение. Ниже приведен сервисный код spring-cometd, который транслирует сообщение по каналу notification после получения сообщения от внешнего события. Клиент java-cometd может успешно получать широковещательные сообщения. Даже клиент javascript может публиковать и подписываться на сообщения на сервисных каналах, но не на широковещательном канале. Подписка осуществляется после рукопожатия.

Код JavaScript:

  var cometd = $.cometd;



  cometd.addListener('/meta/handshake', _metaHandshake);// handshake listener
        cometd.addListener('/meta/connect', _metaConnect);//connection connect listener
        cometd.addListener('/meta/disconnect', _metaDisconnect); 
        cometd.handshake();



  function _metaHandshake(handshake)
            {
                if (handshake.successful === true)  
                {


                    cometd.batch(function()
                    {


                cometd.subscribe('/notification', function(m) {alert("hi"); });



                    });
                }

Что может пойти не так, когда клиент javascript подписывается на широковещательный канал.

@javax.inject.Named // Tells Spring that this is a bean
@javax.inject.Singleton // Tells Spring that this is a singleton
@Service("notificationService")
public class NotificationService {

    private static final String channelName="/notification";
    private static ServerChannel serverChannel;
    private Logger logger = Logger.getLogger(this.getClass());

    @Inject
    private BayeuxServer bayeuxServer;

    @Session
    private LocalSession session;



    @PostConstruct
    public void init()
    {
        logger.debug("Notification Service Initialized");
        channelSetUp();
        session = bayeuxServer.newLocalSession("external");
        session.handshake();

    }


    public void channelSetUp()
    {

        MarkedReference<ServerChannel> channelCreated = bayeuxServer.createChannelIfAbsent(channelName, new ServerChannel.Initializer()
        {
        public void configureChannel(ConfigurableServerChannel channel)
        {
            channel.setPersistent(true);// channel persistent
            channel.addAuthorizer(GrantAuthorizer.GRANT_SUBSCRIBE_PUBLISH); 
        }
        });

        if(channelCreated.isMarked())
        {
            serverChannel = bayeuxServer.getChannel(channelName);

        }
    }






    public void onExternalEvent( Map<String, Object> data)
    {


        // ServerChannel serverChannel = this.bayeuxServer.getChannel(channelName);

    // logger.debug("Notify MessageData from JMS ::" + data.toString());
    if (serverChannel != null)
        {
           // Broadcast the data
        serverChannel.publish(session, data, null);

        }


    }



    @Listener(Channel.META_SUBSCRIBE)  
    public void processSubscription(ServerSession remote, ServerMessage message)
    {   
        // What channel the client wants to subscribe to ?
       String channel = (String)message.get(Message.SUBSCRIPTION_FIELD);
       logger.debug("Client Channel ::"+channel);

    }




}

person user2263197    schedule 07.02.2014    source источник


Ответы (1)


Ваш код клиента правильный.

Код вашего сервера можно улучшить, в частности:

  • Вам не нужно создавать локальный сеанс в init(): аннотация @Session сделает это за вас.
  • Вам не нужно вызывать channelSetup() в init(): просто используйте аннотацию @Configure.
  • Вам не нужно хранить ссылку на ServerChannel: поскольку вы сделали канал постоянным, в onExternalEvent() просто выполните: bayeuxServer.getChannel(channelName).publish(...);

Если вы правильно следовали документации по интеграции Spring и избежали создания 2 экземпляра BayeuxServer (типичная ошибка при использовании Spring), описанных в документации, то все должно быть хорошо.

Я предлагаю вам включить ведение журнала отладки как на клиенте, так и на сервере, и просмотреть журналы, это должно объяснить, почему ваш клиент JavaScript не получает сообщения.

Надеюсь, это помогло!

person sbordet    schedule 07.02.2014
comment
После анализа реальная проблема заключалась в том, что клиент javascript cometd мог получать широковещательное сообщение только тогда, когда клиент подписался до запуска сервера cometd. Когда java-программа на сервере начинает трансляцию, а javascript-кометд подписывается позже. клиент не может получить широковещательное сообщение. - person user2263197; 10.02.2014