jsr356-experts@websocket-spec.java.net

[jsr356-experts] Re: JSR 356 - Maintenance Release Draft - WEBSOCKET_SPEC-226

From: Pavel Bucek <pavel.bucek_at_oracle.com>
Date: Wed, 21 May 2014 22:47:52 +0200

Hello Jean-François,

breaking current commits into different ones would break lots of links
which are already in circulation, so I don't really want to do that. But
what I can do is extract the important changes and put the result here.

*API:*

diff --git a/api/client/src/main/java/javax/websocket/Endpoint.java
b/api/client/src/main/java/javax/websocket/Endpoint.java
index a8f018c..be599aa 100644
--- *a/api/client/src/main/java/javax/websocket/Endpoint.java*
+++ b/api/client/src/main/java/javax/websocket/Endpoint.java
@@ -76,7 +76,7 @@ package javax.websocket;
   *
   * public void onOpen(Session session, EndpointConfig config) {
   * final RemoteEndpoint remote = session.getBasicRemote();
- * session.addMessageHandler(new MessageHandler.Whole&lt;String>() {
+ * session.addMessageHandler(String.class, new
MessageHandler.Whole&lt;String>() {
   * public void onMessage(String text) {
   * try {
   * remote.sendString("Got your message (" + text +
"). Thanks !");

diff --git a/api/client/src/main/java/javax/websocket/Session.java
b/api/client/src/main/java/javax/websocket/Session.java
index 6d6d4fe..0fdab21 100644
--- *a/api/client/src/main/java/javax/websocket/Session.java*
+++ b/api/client/src/main/java/javax/websocket/Session.java
@@ -86,8 +86,13 @@ public interface Session extends Closeable {
       * messages. For further details of which message handlers handle
which of the native websocket
       * message types please see {_at_link MessageHandler.Whole} and
{_at_link MessageHandler.Partial}.
       * Adding more than one of any one type will result in a runtime
exception.
- *
- * <p>See {_at_link Endpoint} for a usage example.
+ * <p>
+ * This method is not safe to use unless you are providing an
anonymous class derived directly
+ * from {_at_link javax.websocket.MessageHandler.Whole} or {_at_link
javax.websocket.MessageHandler.Partial}.
+ * In all other cases (Lambda Expressions, more complex inheritance
or generic type arrangements),
+ * one of the following methods have to be used:
+ * {_at_link #addMessageHandler(Class,
javax.websocket.MessageHandler.Whole)} or
+ * {_at_link #addMessageHandler(Class,
javax.websocket.MessageHandler.Partial)}.
       *
       * @param handler the MessageHandler to be added.
       * @throws IllegalStateException if there is already a
MessageHandler registered for the same native
@@ -96,6 +101,40 @@ public interface Session extends Closeable {
      void addMessageHandler(MessageHandler handler) throws
IllegalStateException;

      /**
+ * Register to handle to incoming messages in this conversation. A
maximum of one message handler per
+ * native websocket message type (text, binary, pong) may be added
to each Session. I.e. a maximum
+ * of one message handler to handle incoming text messages a
maximum of one message handler for
+ * handling incoming binary messages, and a maximum of one for
handling incoming pong
+ * messages. For further details of which message handlers handle
which of the native websocket
+ * message types please see {_at_link MessageHandler.Whole} and {_at_link
MessageHandler.Partial}.
+ * Adding more than one of any one type will result in a runtime
exception.
+ *
+ * @param clazz type of the message processed by message handler
to be registered.
+ * @param handler whole message handler to be added.
+ * @throws IllegalStateException if there is already a
MessageHandler registered for the same native
+ * websocket message type as this
handler.
+ * @since 1.1
+ */
+ public <T> void addMessageHandler(Class<T> clazz,
MessageHandler.Whole<T> handler);
+
+ /**
+ * Register to handle to incoming messages in this conversation. A
maximum of one message handler per
+ * native websocket message type (text, binary, pong) may be added
to each Session. I.e. a maximum
+ * of one message handler to handle incoming text messages a
maximum of one message handler for
+ * handling incoming binary messages, and a maximum of one for
handling incoming pong
+ * messages. For further details of which message handlers handle
which of the native websocket
+ * message types please see {_at_link MessageHandler.Whole} and {_at_link
MessageHandler.Partial}.
+ * Adding more than one of any one type will result in a runtime
exception.
+ *
+ * @param clazz type of the message processed by message handler
to be registered.
+ * @param handler partial message handler to be added.
+ * @throws IllegalStateException if there is already a
MessageHandler registered for the same native
+ * websocket message type as this
handler.
+ * @since 1.1
+ */
+ public <T> void addMessageHandler(Class<T> clazz,
MessageHandler.Partial<T> handler);
+
+ /**
       * Return an unmodifiable copy of the set of MessageHandlers for
this Session.
       *
       * @return the set of message handlers.

*Spec document:*

diff --git a/spec/chapters/applications.tex b/spec/chapters/applications.tex
index 765fac5..01263bc 100644
--- *a/spec/chapters/applications.tex*
+++ b/spec/chapters/applications.tex
@@ -34,6 +34,8 @@ The API limits the registration of
\textbf{MessageHandlers} per \textbf{Session}

  Future versions of the specification may lift this restriction.

+Method \textbf{Session.addMessageHandler(MessageHandler)} is not safe
for use in all circumstances, especially when using Lambda Expressions.
The API forces implementations to get the \textbf{MessageHandler}'s type
parameter in runtime, which is not always possible. The only case where
you can safely use this method is when you are directly implementing
\textbf{MessageHandler.Whole} or \textbf{MessageHandler.Partial} as an
anonymous class. This approach guarantees that generic type information
will be present in the generated class file and the runtime will be able
to get it. For any other case (Lambda Expressions included), one of
following methods have to be used:
\textbf{Session.addMessageHandler(Class$<$T$>$,
MessageHandler.Partial$<$T$>$)} or
\textbf{Session.addMessageHandler(Class$<$T$>$,
MessageHandler.Whole$<$T$>$)}.
+
  \subsection{Sending Messages}

  The Java WebSocket API models each peer of a session with an endpoint
as an instance of the \textbf{RemoteEndpoint} interface. This interface
and its two subtypes (\textbf{RemoteEndpoint.Whole} and
\textbf{RemoteEndpoint.Partial}) contain a variety of methods for
sending websocket messages from the endpoint to its peer.
@@ -47,7 +49,8 @@ public class HelloServer extends Endpoint {
      @Override
      public void onOpen(Session session, EndpointConfig ec) {
          final RemoteEndpoint.Basic remote = session.getBasicRemote();
- session.addMessageHandler(new MessageHandler.Whole<String>() {
+ session.addMessageHandler(String.class,
+ new MessageHandler.Whole<String>() {
              public void onMessage(String text) {
                  try {
                      remote.sendText("Got your message (" + text + ").
Thanks !");


Hope it helps,
Pavel

On 21/05/14 20:18, Jeanfrancois Arcand wrote:
> Pavel,
>
> can you redo the diff that *only* include relevant change? I think it
> worth for all of us to just see what is really changed.
>
> Thanks
>
> -- Jeanfrancois
> On 2014-05-21, 1:49 PM, Pavel Bucek wrote:
>>
>> Please provide any feedback by COB Friday - 5/30/2014. We plan to
>> send this to JCP in the first week of June to start the 30 day review
>> period for this MR.
>>
>> Thanks,
>> Pavel
>>
>> On 21/05/14 11:22, Pavel Bucek wrote:
>>> Hi all,
>>>
>>> as you might have noticed, I filed blocker bug against
>>> WEBSOCKET_SPEC project - [1].
>>>
>>> The main issue is that current Session.addMessageHandler method
>>> cannot handle message handlers in form of lambda expressions,
>>> because there is no information about its generic type parameter
>>> available. We discussed this issue with Brian Goetz and he pointed
>>> out that current API is wrong not only for this case, but also for
>>> more complicated generics usages and is reliable only for anonymous
>>> classes created directly from MessageHandler.Whole and
>>> MessageHandler.Partial (type information is in the generated class
>>> file), so the issue itself is not limited only to Java SE 8.
>>>
>>> We think that this issue is important enough to fix it in a
>>> Maintenance Release as soon as possible, not tied to Java EE 8
>>> planning or anything else.
>>>
>>> Proposed solution is to add two additional Session.addMessageHandler
>>> methods with explicit type information, please see [2] for more
>>> complete description. I also attached updated version of the
>>> specification document. There is only one addition - last paragraph
>>> in chapter 2.1.3 "Receiving Messages" and the sample code in chapter
>>> 2.1.4 "Sending Messages" was modified to use the newly introduced
>>> addMessageHandler method with explicit type.
>>>
>>> Complete change diff can be seen here [3] (but it contains lots of
>>> noise - spec licence etc; changes.txt should be good enough for
>>> evaluation).
>>>
>>> Any feedback would be greatly appreciated!
>>>
>>> Thanks and regards,
>>> Pavel
>>>
>>> [1]: https://java.net/jira/browse/WEBSOCKET_SPEC-226
>>> [2]:
>>> https://github.com/pavelbucek/websocket-spec/blob/WEBSOCKET_SPEC-226/websocket-1.1-changes.txt
>>> [3]: https://github.com/pavelbucek/websocket-spec/pull/1/files
>>
>
>