Package org.zkoss.zk.ui.event.impl

## Class ServerPushEventQueue<T extends Event>

- java.lang.Object
- - org.zkoss.zk.ui.event.impl.ServerPushEventQueue<T>

- All Implemented Interfaces:
    `java.io.Serializable`, `EventQueue<T>`

      public class ServerPushEventQueue<T extends Event>
      extends java.lang.Object
      implements EventQueue<T>, java.io.Serializable

  The default implementation of the server-push based event queue (`EventQueue`).
  Since:
    5.0.0
  Author:
    tomyeh
  See Also:
    Serialized Form

- - ### Constructor Summary

    Constructors
    Constructor | Description
    --- | ---
    `ServerPushEventQueue()` |

  - ### Method Summary

    All Methods Instance Methods Concrete Methods
    Modifier and Type | Method | Description
    --- | --- | ---
    `void` | `close()` | Closes the event queue.
    `boolean` | `isClose()` | Returns whether it is closed.
    `boolean` | `isSubscribed​(EventListener<T> listener)` | Returns if an event listener is subscribed.
    `void` | `publish​(T event)` | Publishes an event.
    `void` | `subscribe​(EventListener<T> listener)` | Subscribes a listener to this queue.
    `void` | `subscribe​(EventListener<T> listener, boolean async)` | Subscribes a synchronous or asynchronous listener to this event queue.
    `void` | `subscribe​(EventListener<T> listener, EventListener<T> callback)` | Subscribes a synchronous or asynchronous listener to this event queue.
    `boolean` | `unsubscribe​(EventListener<T> listener)` | Unsubscribes a listener from the queue.

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Constructor Detail

    - #### ServerPushEventQueue

          public ServerPushEventQueue()

  - ### Method Detail

    - #### publish

          public void publish​(T event)

      Publishes an event. Unlike `DesktopEventQueue`, an event can be published without the current execution (i.e., not in an event listener).
      Specified by:
        `publish` in interface `EventQueue<T extends Event>`
      Parameters:
        `event` - the event to publish.
        Notice that all subscribers will receive the event no matter what the event's name and target are.
        You could publish an anonymous event by `publish(new Event("", null, data))`.

    - #### subscribe

          public void subscribe​(EventListener<T> listener)

      Description copied from interface: `EventQueue`
      Subscribes a listener to this queue. It is the same as `subscribe(listener, false)` (`EventQueue.subscribe(EventListener,boolean)`. In other words, it subscribes a synchronous listener.

      Note: this method must be called within an activated execution (i.e., `Executions.getCurrent()` not null), no matter what scope the event queue is.

      Note: the listener could access the component associated with the event (`Event.getTarget()`), only if this is an `EventQueues.DESKTOP` event queue.

      An event listener can be subscribed multiple times, and it will be invoked multiple times if an event is published.

      Even if this is a `EventQueues.GROUP`, `EventQueues.SESSION`, or `EventQueues.APPLICATION` event queue, the listener is subscribed for the current desktop only, i.e., it can only access the components belong to the subscribed desktop. If you want to use the same listener to manipulate multiple desktops, you have to subscribe them separately when the corresponding execution is available.

      Specified by:
        `subscribe` in interface `EventQueue<T extends Event>`
      See Also:
        `EventQueue.subscribe(EventListener,EventListener)`, `EventQueue.subscribe(EventListener,boolean)`

    - #### subscribe

          public void subscribe​(EventListener<T> listener,
                                EventListener<T> callback)

      Description copied from interface: `EventQueue`
      Subscribes a synchronous or asynchronous listener to this event queue. A synchronous listener works the same as a normal event listener, while an asynchronous listener is executed asynchronously in an working thread. Refer here for details.

      Here is an example,

                  <window title="long operation" border="normal">
                  <zscript>
                  void print(String msg) {
                          new Label(msg).setParent(inf);
                  }
                  </zscript>
                  <button label="async long op">
                          <attribute name="onClick"><![CDATA[
                  if (EventQueues.exists("longop")) {
                   print("It is busy. Please wait");
                   return; //busy
                  }

                  EventQueue eq = EventQueues.lookup("longop"); //create a queue
                  String result;

                  //subscribe async listener to handle long operation
                  eq.subscribe(new EventListener() {
                   public void onEvent(Event evt) { //asynchronous
                     org.zkoss.lang.Threads.sleep(3000); //simulate a long operation
                     result = "success"; //store the result
                   }
                  }, new EventListener() { //callback
                   public void onEvent(Event evt) {
                     print(result); //show the result to the browser
                     EventQueues.remove("longop");
                   }
                  });

                  print("Wait for 3 seconds");
                  eq.publish(new Event("whatever")); //kick off the long operation
                          ]]></attribute>
                  </button>
                  <vbox id="inf"/>
                  </window>

      Notice that, though an asynchronous listener cannot access the desktop and has no current execution, it can invoke `EventQueue.publish(T)` to publish the events. Refer to another example in `EventQueue.subscribe(EventListener,boolean)`.

      Specified by:
        `subscribe` in interface `EventQueue<T extends Event>`
      Parameters:
        `listener` - the asynchronous listener to invoke when an event is received
        `callback` - the callback listener, which will be invoked if the asynchronous listen has been invoked. Unlike the asynchronous listener, the callback listener works like a normal listener. You can access the current execution, and update the desktop.
        Version Difference: since 5.0.8, the event argument is the same as the one passed to `listener`. In the prior version, it is always null for the callback listener.
      See Also:
        `EventQueue.subscribe(EventListener)`, `EventQueue.subscribe(EventListener,boolean)`

    - #### subscribe

          public void subscribe​(EventListener<T> listener,
                                boolean async)

      Description copied from interface: `EventQueue`
      Subscribes a synchronous or asynchronous listener to this event queue. A synchronous listener works the same as a normal event listener, while an asynchronous listener is executed asynchronously in an working thread. Refer here for details.

      The use of synchronous listeners is straightforward -- they are just the same a normal event listener. Here is an example of using an asynchronous listener. In this example, we use an asynchronous listener to execute a long operation, a synchronous listener to update the desktop, and they communicate with each other with events.

      There is another way to do the same job, callback, refer to `EventQueue.subscribe(EventListener,EventListener)` for example.

                  <window title="long operation" border="normal">
                  <zscript>
                  void print(String msg) {
                  new Label(msg).setParent(inf);
                  }
                  </zscript>
                  <button label="async long op">
                  <attribute name="onClick"><![CDATA[
                  if (EventQueues.exists("longop")) {
                   print("It is busy. Please wait");
                   return; //busy
                  }

                  EventQueue eq = EventQueues.lookup("longop"); //create a queue
                  String result;

                  //subscribe async listener to handle long operation
                  eq.subscribe(new EventListener() {
                   public void onEvent(Event evt) {
                     if ("doLongOp".equals(evt.getName())) {
                       org.zkoss.lang.Threads.sleep(3000); //simulate a long operation
                       result = "success"; //store the result
                       eq.publish(new Event("endLongOp")); //notify it is done
                     }
                   }
                  }, true); //asynchronous

                  //subscribe a normal listener to show the result to the browser
                  eq.subscribe(new EventListener() {
                   public void onEvent(Event evt) {
                     if ("endLongOp".equals(evt.getName())) {
                       print(result); //show the result to the browser
                       EventQueues.remove("longop");
                     }
                   }
                  }); //synchronous

                  print("Wait for 3 seconds");
                  eq.publish(new Event("doLongOp")); //kick off the long operation
                  ]]></attribute>
                  </button>
                  <vbox id="inf"/>
                  </window>

      The asynchronous event listener requires Server Push (`ServerPush`).

      If you want to show a busy message to cover a portion of the desktop, use `Clients.showBusy(org.zkoss.zk.ui.Component,String)`

      Note: this method must be called within an activated execution, i.e., `Executions.getCurrent()` not null.

      An event listener can be subscribed multiple times, and it will be invoked multiple times if an event is published.

      Even if this is an application-level or session-level event queue, the listener is subscribed for the current desktop only. If you want to use the same listener for multiple desktops, you have to subscribe them separately when the corresponding execution is available.

      Specified by:
        `subscribe` in interface `EventQueue<T extends Event>`
      Parameters:
        `listener` - the listener
        `async` - whether the listener is asynchronous
      See Also:
        `EventQueue.subscribe(EventListener)`, `EventQueue.subscribe(EventListener, EventListener)`

    - #### isSubscribed

          public boolean isSubscribed​(EventListener<T> listener)

      Description copied from interface: `EventQueue`
      Returns if an event listener is subscribed.

      Notice that this method only checks the listeners subscribed for this desktop. It doesn't check the listeners for other desktops even if this is an application-level or session-level event queue.

      Specified by:
        `isSubscribed` in interface `EventQueue<T extends Event>`

    - #### unsubscribe

          public boolean unsubscribe​(EventListener<T> listener)

      Description copied from interface: `EventQueue`
      Unsubscribes a listener from the queue.

      Note: this method must be called within an activated execution, i.e., `Executions.getCurrent()` not null.

      Notice that this method only unsubscribes the listener subscribed for this desktop. It doesn't check the listeners for other desktops even if this is an application-level or session-level event queue.

      Specified by:
        `unsubscribe` in interface `EventQueue<T extends Event>`
      Returns:
        true if the listener was subscribed.

    - #### close

          public void close()

      Description copied from interface: `EventQueue`
      Closes the event queue. After closed, application cannot access any of its method.

      Don't call this method directly. It is called only internally. Rather, use `EventQueues.remove(java.lang.String)` instead.

      Specified by:
        `close` in interface `EventQueue<T extends Event>`

    - #### isClose

          public boolean isClose()

      Description copied from interface: `EventQueue`
      Returns whether it is closed.
      Specified by:
        `isClose` in interface `EventQueue<T extends Event>`