/** * Instantiate the service. Typically the derived constructor will call {@ #subscribe(String, * String)} to map subscriptions to methods. * * @param bayeux The bayeux instance. * @param name The name of the service (used as client ID prefix). * @param maxThreads The size of a ThreadPool to create to handle messages. * @param synchronous True if message delivery will be synchronized on the client. */ public BayeuxService(Bayeux bayeux, String name, int maxThreads, boolean synchronous) { if (maxThreads > 0) setThreadPool(new QueuedThreadPool(maxThreads)); _name = name; _bayeux = bayeux; _client = _bayeux.newClient(name); _listener = (synchronous) ? new SyncListen() : new AsyncListen(); _client.addListener(_listener); }
/** * Subscribe to a channel. Subscribe to channel and map a method to handle received messages. The * method must have a unique name and one of the following signatures: * * <ul> * <li><code>myMethod(Client fromClient,Object data)</code> * <li><code>myMethod(Client fromClient,Object data,String id)</code> * <li><code>myMethod(Client fromClient,String channel,Object data,String id)</code> The data * parameter can be typed if the type of the data object published by the client is known * (typically Map<String,Object>). If the type of the data parameter is {@link Message} then * the message object itself is passed rather than just the data. * <p>Typically a service will subscribe to a channel in the "/service/**" space which is * not a broadcast channel. Messages published to these channels are only delivered to * server side clients like this service. * <p>Any object returned by a mapped subscription method is delivered to the calling client * and not broadcast. If the method returns void or null, then no response is sent. A mapped * subscription method may also call {@link #send(Client, String, Object, String)} to * deliver a response message(s) to different clients and/or channels. It may also publish * methods via the normal {@link Bayeux} API. * <p> * * @param channelId The channel to subscribe to * @param methodName The name of the method on this object to call when messages are recieved. */ protected void subscribe(String channelId, String methodName) { Method method = null; Class<?> c = this.getClass(); while (c != null && c != Object.class) { Method[] methods = c.getDeclaredMethods(); for (int i = methods.length; i-- > 0; ) { if (methodName.equals(methods[i].getName())) { if (method != null) throw new IllegalArgumentException("Multiple methods called '" + methodName + "'"); method = methods[i]; } } c = c.getSuperclass(); } if (method == null) throw new NoSuchMethodError(methodName); int params = method.getParameterTypes().length; if (params < 2 || params > 4) throw new IllegalArgumentException( "Method '" + methodName + "' does not have 2or3 parameters"); if (!Client.class.isAssignableFrom(method.getParameterTypes()[0])) throw new IllegalArgumentException( "Method '" + methodName + "' does not have Client as first parameter"); Channel channel = _bayeux.getChannel(channelId, true); if (((ChannelImpl) channel).getChannelId().isWild()) { final Method m = method; Client wild_client = _bayeux.newClient(_name + "-wild"); wild_client.addListener( _listener instanceof MessageListener.Asynchronous ? new AsyncWildListen(wild_client, m) : new SyncWildListen(wild_client, m)); channel.subscribe(wild_client); } else { _methods.put(channelId, method); channel.subscribe(_client); } }
/** * Send data to a individual client. The data passed is sent to the client as the "data" member of * a message with the given channel and id. The message is not published on the channel and is * thus not broadcast to all channel subscribers. However to the target client, the message * appears as if it was broadcast. * * <p>Typcially this method is only required if a service method sends response(s) to channels * other than the subscribed channel. If the response is to be sent to the subscribed channel, * then the data can simply be returned from the subscription method. * * @param toClient The target client * @param onChannel The channel the message is for * @param data The data of the message * @param id The id of the message (or null for a random id). */ protected void send(Client toClient, String onChannel, Object data, String id) { toClient.deliver(getClient(), onChannel, data, id); }