问题
It seems that the javascript client cannot subscribe to the broadcast channel or receive the message from it. Below is the spring-cometd service code that broadcast the message on the notification channel after receiving message from external event. The java-cometd client can receive the broadcast messages sucessfuly. Even the javascript client can publish and subscribe the messages on service channels but not on broadcast channel. The subscription is done after the handshake.
JavaScript Code:
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"); });
});
}
What could go wrong when javascript client subscribe to the broadcast channel.
@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);
}
}
回答1:
Your client code is correct.
Your server code can be improved, in particular:
- You don't need to create a local session in
init()
: the@Session
annotation does it for you. - You don't need to call
channelSetup()
ininit()
: just use a@Configure
annotation. - You don't need to store a reference to the
ServerChannel
: since you made the channel persistent, inonExternalEvent()
just do:bayeuxServer.getChannel(channelName).publish(...);
If you have followed correctly the documentation for the Spring integration, and avoided the creation of 2 BayeuxServer
instances (a typical error when using Spring) described in the documentation, then you should be good to go.
I suggest that you enable debug logging in both client and server, and look at the logs, that should explain why your JavaScript client does not receive the messages.
Hope that helped !
来源:https://stackoverflow.com/questions/21636294/cometd-javascript-client-doesnt-subscribe-to-broadcast-channel