<< Back to previous view

[WEBSOCKET_SPEC-225] Add method to asynchronously send messages of unkown length Created: 04/Apr/14  Updated: 04/Apr/14

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: stuartdouglas Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: stuartdouglas

 Description   

At the moment RemoteEndpoint.Async only has methods that send messages of a known length that are fully buffered in memory. It would be good if this could be extended to also include some way of sending messages piecemeal.

At the moment this can be accomplished using RemoteEndpoint.Basic using the stream and writer, however this requires the use of blocking IO.

As a suggestion as to what this API could look like maybe something like:

void sendPartialText(String message, PartialCallback back);

interface PartialCallback {

   void onWritePossible(TextSender sender);

}

interface TextSender {
  boolean isReady();
  void send(String text, boolean last);
}





[WEBSOCKET_SPEC-224] Consider NOOP default interface methods implementation - Encoder/Decoder init/destroy - Java SE 8 Created: 01/Apr/14  Updated: 01/Apr/14

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: 1.0
Fix Version/s: 2.0

Type: Improvement Priority: Major
Reporter: Pavel Bucek Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: Pavel Bucek




[WEBSOCKET_SPEC-223] Performance impact of RemoteEndPoint async threading model Created: 12/Mar/14  Updated: 13/Mar/14

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: 1.0
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: gregwilkins Assignee: Unassigned
Resolution: Unresolved Votes: 2
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: asynchronous callback
Participants: gregwilkins

 Description   

In the RemoteEndPoint javadoc, http://docs.oracle.com/javaee/7/api/javax/websocket/RemoteEndpoint.Async.html, it says:

"The completion handlers for the asynchronous methods are always called with a different thread from that which initiated the send."

This has a significant detrimental impact on performance, requiring a dispatch to a new thread after ever sent message, even when operating in batching mode when the send involves only a copy into a buffer and no IO.

It is a very common pattern in asynchronous IO APIs to allow callbacks to happen on the calling thread. While this can give issues with depth of recursion, there are techniques available to avoid that and the performance gains that result are well worth it.

At the very least, this behaviour should be modal and an option provided to allow it to be turned off if applications and/or frameworks are prepared to make the effort to avoid deep recursion.






[WEBSOCKET_SPEC-222] Implement RFC6570 (URI Template) Level 2 Created: 13/Feb/14  Updated: 13/Feb/14

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: ccidraljr Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: ccidraljr

 Description   

Are there plans to implement the Level 2 of the URI template specification? That would be greatly useful for framework developers who want to base their implementations on the JSR-356.






[WEBSOCKET_SPEC-220] Spec should explicitly specify the behaviour of encoders when a sub class is returned Created: 10/Jan/14  Updated: 10/Jan/14

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: 1.0
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: stuartdouglas Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: markt_asf, Pavel Bucek and stuartdouglas

 Description   

I have had a user file an issue because when attempting to match encoders I am only considering the encoder if the type to encoded exactly matches the encoder type (https://issues.jboss.org/browse/UNDERTOW-166).

The user was expecting that if they returned a sub class of a class for which there was an encoder registered from their @OnMessage method it would also be handed by the encoder.

As far as I can tell the spec does not really say anything about this situation, so I think it would be good to clarify what the intended behaviour is.



 Comments   
Comment by markt_asf [ 10/Jan/14 12:27 PM ]

For the record, Tomcat uses isAssignableFrom() rather than an exact match in this case. I don't see anything in the EG archives that indicates an explicit intention.

Comment by Pavel Bucek [ 10/Jan/14 01:29 PM ]

Tyrus (glassfish/weblogic) also does isAssignableFrom(). Same as Mark, I was not able to find anything in the spec or archives which would state how it should work, but I don't see any reason why we should limit it to exact match.

Comment by stuartdouglas [ 10/Jan/14 01:37 PM ]

In that case I will change the Undertow behaviour to match.





[WEBSOCKET_SPEC-219] The HttpSession and ServletContext are hard to retrieve: Add argument types for @OnOpen, @OnMessage, @OnError, and @OnClose methods Created: 07/Dec/13  Updated: 07/Dec/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: 2.0
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: Nick Williams Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: httpsession servlet-context
Participants: Nick Williams

 Description   

The HTTP session (HttpSession) and application context (ServletContext) are hard to retrieve within a server endpoint right now. The HTTP session can only be retrieved as described in WEBSOCKET_SPEC-218. The ServletContext can only be retrieved if the HTTP session exists and if it is HttpSession, and requires retrieving the HttpSession and calling its getServletContext method.

WEBSOCKET_SPEC-217 and WEBSOCKET_SPEC-218 describe enhancements to make retrieving the HTTP session and application context easier. However, there's an even easier approach that can be implemented.

@OnOpen, @OnMessage, @OnError, and @OnClose methods can have several different types of arguments that the container automatically supplies, such as the Session and various @PathParam arguments, EndpointConfig for @OnOpen, CloseReason for @OnClose, Throwable for @OnError, and various message objects for @OnMessage. I recommend adding the following valid method parameters for all four annotations:

  • The application context for the deployed application (in a Servlet container, this is a javax.servlet.ServletContext parameter), never null.
  • The HTTP session object linked to the handshake request for this Session (in a Servlet container, this is a javax.servlet.http.HttpSession parameter), null if no HTTP session existed for the handshake request.

This would make generically retrieving the application context (ServletContext) and HTTP session (HttpSession) much easier.






[WEBSOCKET_SPEC-218] The HttpSession is hard to retrieve: Add getHttpSession method to Session Created: 07/Dec/13  Updated: 07/Dec/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: 2.0
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: Nick Williams Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: httpsession
Participants: Nick Williams

 Description   

Currently, the only way to retrieve the HTTP session (such as the Servlet API's HttpSession) is to call HandshakeRequest's getHttpSession method. Getting the HTTP session is very often required within a WebSocket, and this design means every server endpoint must have the following configurator to expose the session to the rest of the endpoint methods:

public static class EndpointConfigurator extends ServerEndpointConfig.Configurator
{
    @Override
    public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response)
    {
        super.modifyHandshake(config, request, response);

        config.getUserProperties().put("someSessionPropertyName", request.getHttpSession());
    }
}

And then later in an endpoint method:

...
    @OnOpen
    public void sessionOpened(Session session)
    {
        HttpSession httpSession = (HttpSession)session.getUserProperties.get("someSessionPropertyName");
    }
...

I suggest that the HandshakeRequest isn't the only interface that needs a getHttpSession method. We should add an Object getHttpSession() method to the Session interface as well. I'm aware that the HTTP session can time out before the Session, but the fact remains that there is never more than one HTTP session per Session, that the HTTP session never changes during the life of the Session, and that when the Session is initially created during the HTTP request an HTTP session may exist for that HTTP request.

Like its counterpart on HandshakeRequest, Session's getHttpSession method should return null if no HTTP session existed when the WebSocket connection was opened.






[WEBSOCKET_SPEC-217] It is not easy to get to the ServletContext in a websocket session Created: 07/Dec/13  Updated: 07/Dec/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: 1.0
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: jcompagner Assignee: Unassigned
Resolution: Unresolved Votes: 1
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: jcompagner and Nick Williams

 Description   

You could use a Configurator for this:

public class GetServletContextConfigurator extends ServerEndpointConfig.Configurator
{
@Override
public void modifyHandshake(ServerEndpointConfig config,
HandshakeRequest request,
HandshakeResponse response)

{ EndpointConfig.getUserProperties().put("ServletContext",((HttpSession)request.getHttpSession()).getServletContext()); }

}

But that doesn't work for me, because there is no http session..
and the above call does not create it. It could be made that that always just creates a session, but can then a jsessionid cookie be send back over that upgraded websocket request so that the browser does use that?

I need the ServletContext to read files and that kind of stuff right from the WAR. Its impossible to get to that directory (or war file itself if it is not extracted) in side a websocket.

I think what we need is

EndpointConfig.getUserProperties().put("ServletContext",request.getServletContext());

or something like that.



 Comments   
Comment by Nick Williams [ 07/Dec/13 03:19 PM ]

I would suggest adding a getHttpContext (alternatively getApplicationContext) method to WebSocketContainer:

public interface WebSocketContainer
{
    ...
    /*
     * Returns the HTTP application context for the current deployed application. This can be anything,
     * but in a Servlet API environment it should be a {@code javax.servlet.ServletContext}.
     * 
     * @return the HTTP application context, such as the {@code ServletContext}, but never {@code null}.
     */
    Object getHttpContext();
    ...
}

If provided in this manner, getting a ServletContext is as simple as, using a Session as an example, this:

...
    @OnOpen
    public void sessionOpened(Session session)
    {
        ServletContext context = (ServletContext)session.getContainer().getHttpContext();
    }
    ...




[WEBSOCKET_SPEC-216] Need an abort() method and a async close() method for Websockets Created: 28/Oct/13  Updated: 28/Oct/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: 1.0
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: preisser144 Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: preisser144

 Description   

In Websocket 1.0, the javax.websocket.Session class provides methods #getBasicRemote() and #getAsyncRemote() which returns different RemoteEndpoints for either sending message synchronously (RemoteEndpoint.Basic) or asynchronously (RemoteEndpoint.Async).

However, to close a Websocket session (send the closing handshake) the only method is javax.websocket.Session#close(...). As it is a synchronous method it may block if there is no window on the underlying TCP connection to send the closing handshake. This can be a problem for implementations that only use Async I/O for sending Websocket message which are then forced to use Sync/Blocking I/O for sending the closing handshake.
(For example, in .Net, there is System.Net.WebSockets.WebSocket#CloseOutputAsync() method that async closes the WebSocket session.)

Also, javax.websocket.Session does not have a method to abort a WebSocket connection immediately. This might be needed for an application that needs to disconnect a Client e.g. as DoS prevention (for example, when a connected client reads data from the underlying TCP connection very slowly so that the App needs to buffer more and more messages for that client, the application may want to immediately abort the WebSocket connection).
Currently this is not possible - the App would need to wait to be able to send the closing handshake.
(For example, in .Net there is System.Net.WebSockets.WebSocket#Abort() method that immediately aborts the WebSocket connection and cancels all pending I/O operations.)

Please see the thread on [1] for a discussion on Tomcat's Users list about these issues.

[1] http://markmail.org/message/z2pxdxeto656byu3






[WEBSOCKET_SPEC-215] Clarify relationship between EndpointConfig#getUserProperties() and Session#getUserProperties() Created: 28/Oct/13  Updated: 28/Oct/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: 1.0
Fix Version/s: None

Type: Bug Priority: Major
Reporter: markt_asf Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: markt_asf

 Description   

A question was asked[1] about Tomcat's WebSocket implementation that referenced this stack overflow question[2]. Joakim's response looks perfectly reasonable to me (Tomcat does something similar but slightly different which is what triggered the question about Tomcat's implementation) but I have checked the spec document, the Javadoc and the EG list archive and can't find anything to support / justify this behavior. Have I missed something?

I think Jetty's current implementation is the right way to go and I'll be tweaking Tomcat's to align with it shortly but - assuming I haven't missed something in the spec - it would be good to add a suitable clarification to the specification and/or Javadoc.

[1] http://markmail.org/message/aupved2rv3p2dtwl
[2] http://stackoverflow.com/questions/17936440/accessing-httpsession-from-httpservletrequest-in-a-web-socket-socketendpoint/17994303#17994303






[WEBSOCKET_SPEC-214] Introduce non-blocking WebSocketContainer.connectToServer Created: 28/Aug/13  Updated: 28/Aug/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: 1.0
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: Pavel Bucek Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: Pavel Bucek

 Description   

WebSocketConatiner.connectToServer currently blocks until handshake response is received, which is not very usable in some cases, like applications with UI etc. connectToServer paralell in java scipt already is non-blocking and seems like it is working very well and users might expect similar behaviour from WebSocket client.

I could see something similar to what is already present, but it would need to return Future<Session> and report DeploymentException (and others) via this returned future.

Based on user submission, see https://java.net/jira/browse/TYRUS-243






[WEBSOCKET_SPEC-212] Give WebSocketContainer on the client side a lifecycle Created: 01/Aug/13  Updated: 01/Aug/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: dannycoward Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: dannycoward

 Description   

Currently there is no way for the implementation to know when the developer has finished using each instance of the WebSocketContainer. If the developer uses ContainerProvider.getWebSocketContainer() to obtain many instances, this is difficult to manage for the implementation.

Consider adding a lifecycle so the implementation can clean up.






[WEBSOCKET_SPEC-211] Remove restriction on when a server endpoint can be deployed Created: 26/Jul/13  Updated: 06/Aug/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: 1.0
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: rstoyanchev Assignee: Unassigned
Resolution: Unresolved Votes: 9
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: martin_grigorov and rstoyanchev

 Description   

Section 6.4 explicitly restricts server endpoints from being deployed once the server is up and running:

Developers may deploy server endpoints programmatically by
using one of the addEndpoint methods of the ServerContainer
interface. These methods are only operational during the
application deployment phase of an application. Specifically,
as soon as any of the server endpoints within the application 
have accepted an opening handshake request, the apis may not
longer be used. This restriction may be relaxed in a future
version.

There are cases however when it is useful to have consolidated handling of HTTP requests including WebSocket handshake requests. For example SockJS (a protocol for WebSocket fallback options) expects URLs (see the "Session URLs" section) with the pattern "/endpointPrefix/<server>/<session>/<transport>" where <transport> can be HTTP-based (e.g. HTTP streaming, long polling) or WebSocket. The most natural way to implement this is to create a single servlet SockJS that handles all requests under "/endpointPrefix" including requests for "/endpointPrefix/*/*/websocket". This is known as front servlet and it's what virtually all web frameworks have.

I can imagine there are other cases where it is not possible to determine the URL at which an endpoint should be deployed at startup (e.g. SAAS product that lets configure and use cloud-based services). It would be useful to have more examples here.

It's worth pointing out that WebSocket APIs in Java and outside of Java consistently provide a way to do this, i.e. integrate WebSocket handshakes into existing HTTP request handling mechanisms (Jetty 9, Netty, vert.x, socket.io, etc.)



 Comments   
Comment by martin_grigorov [ 06/Aug/13 06:56 AM ]

This request is related to https://java.net/jira/browse/WEBSOCKET_SPEC-181.

Comment by rstoyanchev [ 06/Aug/13 03:33 PM ]

Based on the experience with a similar request in Tomcat, I want to clarify what I have in mind is the ability to initiate an upgrade from a Servlet or Filter, which is different from deployment via ServerContainer.addEndpoint. Something along the lines of:

HandshakeRequest request = ...
HandshakeResponse response = ...

ServerContainer container = ... 

container.upgrade(request, response, endpoint);

The above is not a concrete proposal, it's just an example to make clear the intent of the request.





[WEBSOCKET_SPEC-210] Introduce API for Client-side SSL Configuration Created: 22/Jul/13  Updated: 22/Jul/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: 1.0
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: Pavel Bucek Assignee: Unassigned
Resolution: Unresolved Votes: 1
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: Pavel Bucek




[WEBSOCKET_SPEC-209] Unclear definition of sendBinary behavior with respect to ByteBuffer in RemoteEndponts sendBinary call Created: 28/Jun/13  Updated: 28/Jun/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: 2.0
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: Niki Dokovski Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: Niki Dokovski

 Description   

The specification and javadoc do not define what could be an impact of sendBinary call over the ByteBuffer it operates upon. The buffer's position could be both changed or not. Hence there are two valid implementations of this method which will lead to non portable application, simply because the app would be adjusted to the concrete implementation behavior. Any other container which has different implementation strategy would break the app. What is the recommendation in respect to this and can it be documented in a spec revision?






[WEBSOCKET_SPEC-208] Misleading javadoc in Decoder.destroy method Created: 21/Jun/13  Updated: 21/Jun/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: 1.0
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Niki Dokovski Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: Niki Dokovski

 Description   

Current javadoc http://docs.oracle.com/javaee/7/api/javax/websocket/Decoder.html#destroy() says
"This method is called when the decoder is about to be removed from service in order that any resources the encoder used may be closed gracefully." Where it should be ... decoder used my be closed gracefully






[WEBSOCKET_SPEC-207] ServerEndpointConfig$Configurator getter for default platform configurator Created: 17/Jun/13  Updated: 17/Jun/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: stepan.kopriva Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
blocks TYRUS-196 Implement correct @PreDestroy calling... Open
Tags:
Participants: stepan.kopriva

 Description   

Please provide getter for containerDefaultConfigurator in ServerEndpointConfig$Configurator. The access to the configurator is needed to be able to call @PreDestroy for CDI beans






[WEBSOCKET_SPEC-206] Misleading JavaDoc in Session connectToServer(Object annotatedEndpointInstance, URI path) throws DeploymentException, IOException Created: 03/Jun/13  Updated: 03/Jun/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: 1.0
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Niki Dokovski Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: Niki Dokovski

 Description   

Current javadoc states the following "Connect the supplied annotated endpoint instance to its server. The supplied object must be a class decorated with the class level ServerEndpoint annotation. .... "
In fact, the annotation that should be used on the supplied object is ClientEndpoint. As this is the peer that initiates the connection.






[WEBSOCKET_SPEC-205] Need a way to configure WebSocketContainer Created: 30/May/13  Updated: 30/May/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: jitu Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: jitu

 Description   

Need a way to configure the WebSocketContainer (for e.g thread pool, say security configuration etc). This way one can customize the container with a standard configuration or can extend it using a provider specific configuration.

Suggesting a new method
ContainerProvider#getWebSocketContainer(Map<String, ?> config)






[WEBSOCKET_SPEC-204] WebSocket client API should be moved to Java SE Created: 24/May/13  Updated: 24/May/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: reza_rahman Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: reza_rahman

 Description   

The WebSocket client API should be moved to Java SE so clients can use them without having to introduce an additional dependency.

Do let me know if anything needs to be explained further - I am happy to help.

Please note that these are purely my personal views and certainly not of Oracle's as a company.






[WEBSOCKET_SPEC-203] Clarify session.getRequestParameterMap() returns the elements of the query string Created: 21/May/13  Updated: 07/Dec/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: dannycoward Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: dannycoward and Nick Williams

 Description   

as synopsis, tweak javadoc to spell it out



 Comments   
Comment by Nick Williams [ 07/Dec/13 03:25 PM ]

I could be wrong, but I thought it returned more than just the parameters from the query string. Doesn't it also return the x-www-form-urlencoded parameters from the request body (e.g., post variables)?





[WEBSOCKET_SPEC-202] Missing proxy configuration support in WebSocket API Created: 17/May/13  Updated: 30/May/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: 1.0
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: Niki Dokovski Assignee: Unassigned
Resolution: Unresolved Votes: 1
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: markt_asf and Niki Dokovski

 Description   

Currently there is no spec defined mechanism for providing proxy configurations when ClientEndpoint is behind a http proxy. There are multiple variations of implementations but still such configuration could be interfaced in spec defined way so that connectToServer methods in WebSocketContainer respect that.



 Comments   
Comment by markt_asf [ 30/May/13 02:33 PM ]

java.net.ProxySelector looks to be the best way to do this at the moment. It is pluggable and falls back to the system properties.

The main question is should the URI passed to it be ws/wss or http/https?

ws/wss
Pros - allows different proxies to be used for web socket and http connections
Cons - not currently supported by ProxySelector

http/https
Cons - does not allow for different proxies for web socket and http
Pros - currently supported by ProxySelector

There is currently no way to differentiate between a "scheme not supported" response and an explicit "don't use a proxy for that scheme" response. Differentiation between the two would require a custom ProxySelector.

I'm leaning towards ws/wss and requiring a custom ProxySelector as that allows for a clear distinction between WebSocket and HTTP traffic.





[WEBSOCKET_SPEC-200] Inconsistent limitations on @PathParam types Created: 15/May/13  Updated: 15/May/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: 1.0
Fix Version/s: None

Type: Bug Priority: Major
Reporter: gdavison Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: gdavison

 Description   

In the JSR spec section 4.3 it states that @PathParam can be used on "parameters are String, any Java Primitive type, or boxed version thereof". But in sections 4.4->4.7 they say "zero to n String parameters annotated with @PathParam annotations".

Sections 4.4->4.7 should be updated to be consistent with section 4.3






[WEBSOCKET_SPEC-199] Add the ability to define filters and interceptors Created: 10/May/13  Updated: 13/May/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: reza_rahman Assignee: Unassigned
Resolution: Unresolved Votes: 8
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: gdavison and reza_rahman

 Description   

In a future version of the WebSocket API, I would love to see the ability to specify filters and interceptors both on the client and server side. This could be very similar to how you can specify JAX-RS 2 filters and interceptors today (e.g. for encryption, compression, etc). Perhaps this could even be done via CDI interceptors somehow.

Do let me know if anything needs to be explained further - I am happy to help.

Please note that these are purely my personal views and certainly not of Oracle's as a company.



 Comments   
Comment by gdavison [ 13/May/13 12:12 PM ]

Specific use case:

"In section 4.3 of the JSR 356 spec there is an example of using a @PathParam to map part of the path to a parameter, but as per RFC 6455 4.2.2. it should be possible to return a 404 status code without initiating a WebSocket interchange.

I can't find an obvious code path to do this as presumable onOpen is too late as a message has already been send down the connection. Is there a -RS like request filter available so we can intercept this?'





[WEBSOCKET_SPEC-198] Add the ability to define global encoders and decoders Created: 10/May/13  Updated: 07/Dec/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: reza_rahman Assignee: Unassigned
Resolution: Unresolved Votes: 7
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: Nick Williams and reza_rahman

 Description   

In a future version of the WebSocket API, I would love to see the ability to specify global encoders and decoders both of the client and server side. This could be very similar to how you can specify JAX-RS 2 providers today (e.g. to globally handle JSON encoding/decoding with a generic tool).

Do let me know if anything needs to be explained further - I am happy to help.

Please note that these are purely my personal views and certainly not of Oracle's as a company.



 Comments   
Comment by Nick Williams [ 07/Dec/13 03:33 PM ]

We could add a new annotation, @WebSocketCodecs, that can be applied to types used as WebSocket messages. For example:

@WebSocketCodecs(
        encoders = { MyEncoderText.class, MyEncoderBinary.class },
        decoders = { MyDecoderText.class, MyDecoderBinary.class }
)
public class MyMessageObject
{
    ...
}

The encoders and decoders attributes must have at least one and may have at most four values: a text encoder/decoder, a binary encoder/decoder, a text stream encoder/decoder, and a binary stream encoder/decoder.





[WEBSOCKET_SPEC-197] Better define integration with EJB and CDI Created: 10/May/13  Updated: 18/Dec/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: New Feature Priority: Major
Reporter: reza_rahman Assignee: Unassigned
Resolution: Unresolved Votes: 9
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
blocks TYRUS-260 enable CDI in Encoders/Decoders Resolved
Related
is related to TYRUS-281 Client does CDI/EJB lookup Resolved
Tags:
Participants: reza_rahman

 Description   

One of the items I would like to see better addressed in a future WebSocket API version is integration with EJB and CDI.

The case for CDI integration is likely fairly self-explanatory so there no point repeating it. However, perhaps it is important to make the case for EJB integration. Direct EJB integration is a very good fit for RAD code where transactions, persistence, etc are used directly in a WebSocket service. Now while much of this functionality is available outside EJB, some of it is not such as thread safety, asynchronous processing and scheduling. Specifically it may be important to hash out the following questions:

1. Do stateless session beans map to WebSocket endpoints (the likely answer is no)?
2. Can stateful session beans be WebSocket endpoints? I think the likely answer is yes if you treat the WebSocket session as an EJB session, hence having a stateful session bean instance per remote client. @Remove could be called automatically when the WebSocket session is closed (just like CDI conversations).
3. Can singleton session beans be WebSocket endpoints? I think the likely answer is yes and it would provide very useful thread safety services across all remote clients on an endpoint (that can be fine tuned as needed).
4. Is the caller Principal passed on to EJB from WebSocket (I think the answer is yes)?
5. WebSocket could have some really nice synergy with @Asynchronous.
6. What methods can overlap with @Schedule, EJB life-cycle callbacks and other remote/local end-points?

There are similarly interesting questions to address as to CDI integration:

1. Will @Transactional work in a WebSocket endpoint? How about @Observes, @Stereotype, @Produces, @Disposes, etc?
2. Perhaps @Dependent could fit per-peer model?
3. @ApplicationScoped/@Singleton would be a good fit for a shared endpoint model.
4. @ConversationScoped, @RequestScoped probably do not map well to WebSocket.
5. I think @SessionScoped would be a great fit for a instance per-peer model, provided HTTP session ~= WebSocket peer.

Do let me know if anything needs to be explained further - I am happy to help.

Please note that these are purely my personal views and certainly not of Oracle's as a company.






[WEBSOCKET_SPEC-196] WebSocket Spec does not define the activation requirements of CDI Contexts Created: 07/May/13  Updated: 18/Dec/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: 1.0
Fix Version/s: None

Type: Bug Priority: Major
Reporter: John D. Ament Assignee: Unassigned
Resolution: Unresolved Votes: 1
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Dependency
blocks TYRUS-260 enable CDI in Encoders/Decoders Resolved
Related
is related to JMS_SPEC-121 Injection of JMSContext objects not p... Open
is related to TYRUS-281 Client does CDI/EJB lookup Resolved
Tags:
Participants: John D. Ament

 Description   

Currently, a few issues are floating around regarding WebSocket spec and the activation (or lack there of) of CDI contexts. As was the case for the JMS spec & the JSF spec, the WebSocket spec must define what the activation is for CDI contexts when it comes to its methods. For example, "managed bean" is only mentioned once in the PFD however its notion is ambiguous:

Some of the non-api features of the Java WebSocket API are optional when the API is not implemented as part of the full Java EE platform, for example, the requirement that websocket endpoints be non-contextual managed beans (see Chapter 7). Such Java EE only features are clearly marked where they are described.

There is nothing in Chapter 7 that mentions "managed bean" as indicated in this chapter. So in my opinion, I think it's needed for the WebSocket spec to spell out that it expects Request Scope to be enabled during an @OnMessage method, and as a result must ensure that the context is initialized when the method is called.






[WEBSOCKET_SPEC-195] Clarify path param (URI template) matching behavior of trailing '/' in incoming path Created: 18/Apr/13  Updated: 23/Apr/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: joakimerdfelt Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: dannycoward, joakimerdfelt and markt_asf

 Description   

As mentioned in jsr356-experts:
http://java.net/projects/websocket-spec/lists/jsr356-experts/archive/2013-04/message/15

In the email http://java.net/projects/websocket-spec/lists/jsr356-experts/archive/2013-03/message/33
From: Danny Coward
Subject: Closing the gaps in the URI matching specification
Date: Mon, 18 Mar 2013 17:12:35 -0700

He gives a particular example ...

(snip)
suppose we have three endpoints and their paths:
endpoint A: /a/{var}/c
endpoint B: /a/b/c
endpoint C: /a/{var1}/{var2}
incoming URI: a/b/c matches B, not A or C, because an exact match is preferred.
incoming URI: a/d/c matches A with variable var=d, because like goldlocks, its just right
incoming URI: a/x/y/ matches C, with var1=x, var2=y
(/snip)

I have issue with In the last match of incoming path "a/x/y/" (note the trailing slash)
I feel this is a bad behavior of the matching.

A scenario to ponder this behavioral quirk.

endpoint A: "/a/{var}/c/"
endpoint B: "/a/b/c"
endpoint C: "/a/{var1}/{var2}"
endpoint D: "/a/{var1}/{var2}/{var3}"

What should the incoming path "/a/x/y/" match?
Is it endpoint C with ...
var1 = "x"
var2 = "y"
or is it endpoint D with ...
var1 = "x"
var2 = "y"
var3 = ""

I don't think it should match C as the incoming path has the trailing slash indicating another path segment.
Since we are calling this whole concept PathParam, I feel that this would keep us consistent as well.



 Comments   
Comment by markt_asf [ 19/Apr/13 10:29 PM ]

RFC3986 essentially says it is up to us how to handle trailing /.

I currently prefer the position that /a/b != /a/b/ and that /a/b/ does not match /a/{var}

This is closely aligned with how to handle //.

Comment by dannycoward [ 23/Apr/13 11:12 PM ]

Yes I think /a/b != /a/b/, especially because some http servers in front of the websocket impl may find the difference significant.





[WEBSOCKET_SPEC-194] Clarify what is a valid WebSocket path spec syntax Created: 18/Apr/13  Updated: 23/Apr/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: joakimerdfelt Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: dannycoward, joakimerdfelt and markt_asf

 Description   

As brought up in jsr356-experts:
http://java.net/projects/websocket-spec/lists/jsr356-experts/archive/2013-04/message/6

What would be a valid websocket path spec syntax?

Some examples of GOOD path specs:

"/bookings/{guest-id}" - section 4.1.1 and 4.3
"/rewards/{vip-level}" - section 4.3
"/hello" - section 2.1.4
"/a/b/"
"/a/{foo}"
"/{bar}"
"/{bar}/b/c"
"/a/{var}/c"
"/a/b/c"
"/a/{var1}/{var2}"
"/{var1}/d"
"/b/{var2}"

Some examples of BAD path specs:

"/a/b{var}" - variable does not encompass whole path segment
"a/{var}" - no start slash
"/a/{var/b}" - path segment separator in variable name
"/{var}/*" - no globs allowed
"/{var}.do" - variable does not encompass whole path segment
"/a/{var*}" - use of glob character not allowed in variable name.
"/a/{}" - no variable name declared
"/a/{---}" - no alpha character in variable name declared
"{var}" - no start slash
"/a/{my special variable}" - bad syntax for variable name, spaces used
"/a/{var}/{var}" - duplicate variables (case sensitive)
"/a/{var}/{Var}/{vAR}" - duplicate variables (case insensitive)
"/a/../../{var}" - path navigation
"/a/./{var}" - path navigation
"/a//{var}" - empty path segment

There are a number of things that could be better defined for valid path specs.
Here's an example of some of the rules.

1) Path Specs must start with "/" character
2) A "path segment" is all characters between separators "/"
3) A single path segment must be either a literal set of characters or a path param variable, but not both.
4) A path segment cannot use the characters '{', '}', '/', or '*'
5) path navigation sequences "/../", "/./", and "//" cannot be used
6) Variable names must conform to the established variable name syntax ( see WEBSOCKET_SPEC-193 )
7) Duplicate variables names are not allowed to be present in path spec
8) Variable names are case-insensitive



 Comments   
Comment by markt_asf [ 19/Apr/13 10:27 PM ]

I agree with rules 1, 2, 3, 4, 6, 7

re rule 5: Need to decide how to handle //. Not sure about this yet.
re rule 8: RFC6570 says variable names are case sensitive.

note: RFC6570 is stricter than rule 4.

Comment by dannycoward [ 23/Apr/13 10:59 PM ]

This is a good list, but much of it is already covered in the spec.

1. See ServerEndpointConfig.Builder.create() or ServerEndpoint.value()

2, 3, 4, 6, 8 are definied in the URI spec and/or the URI-template spec (e.g. section 2)

7) We should clarify in the spec (thankyou)

On 5), my read of RFC2396 is that '//' is not a valid URI ? And that "/../.." is OK to use.

Comment by joakimerdfelt [ 23/Apr/13 11:48 PM ]

Since we are following RFC6570, then #8 (variable names are case-insensitive) isn't correct.

Section 2.3 Variables
http://tools.ietf.org/html/rfc6570#section-2.3

Regarding the path navigation sequences...
In servlet-3_0-mrel-spec.pdf section 14.2 - Rules for Processing the Deployment Descriptor
The servlet container is expected to canonicalize paths while resolving the deployment descriptor, and also (in a later part of the spec) resolve paths before passing them onto the matching of paths to servlets.

That has 2 parts to be concerned about.
part 1) the @ServerEndpoint("/path") definition should be canonicalized by the implementation.

This could prove problematic for RFC6570 variables using `pct-encoded` form, as the decoding process could decode things prior to working with the URI template.
Eg: defined as "/path/../{%40hi}" - canonicalized to "/path/{@hi}" - now invalid per RFC6570 variable naming rules.
Not an impossible scenario, but a good gotcha waiting for implementors.

part 2) the incoming request should be resolved/canonicalized before attempting matching.
Seems sensible, and its what all good servlet containers do already prior to servlet/filter matching. But our JSR doesn't mandate a servlet container, so it would be good to mention for implementors that this should be done.





[WEBSOCKET_SPEC-193] Clarify what is a valid WebSocket path spec variable name Created: 18/Apr/13  Updated: 23/Apr/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: joakimerdfelt Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: dannycoward, joakimerdfelt and markt_asf

 Description   

As brought up in jsr356-experts:
http://java.net/projects/websocket-spec/lists/jsr356-experts/archive/2013-04/message/6

What makes up a valid websocket path spec variable name?

Some examples of bad path specs with variable names present:

1) "/a/{var/b}" - path segment separator in variable name
2) "/a/{var*}" - use of glob character not allowed in variable name.
3) "/a/{}" - no variable name declared
4) "/a/{---}" - no alpha variable name declared
5) "/a/{my special variable}" - spaces not allowed

Example #1, it could be allowed as a funky variable named "var/b", but is this something we should alert the user of as a possible typo?

Example #2, it could also be allowed as a funky variable named "var*", again, this should probably be alerted to the user as bad form.

Example #3 has no variable name, it should just be forbidden

Example #8, it could also be a funky variable named "---".

Should we restrict the allowable variable names to conform to some sort of limited scope of characters? Say regex "[a-zA-Z0-9._-]*" ?

It was brought up that RFC 6570 already provides some suitable limits for variable names.

Looks like Section 2.3. Variables has the details.
http://tools.ietf.org/html/rfc6570#section-2.3

Looks like it would allow for pct-encoded (Section 1.5) in varname.
Sounds reasonable.

To translate what I see.
varchar = (ALPHA / DIGIT / "_" / pct-encoded)
varname = varchar *( ["."] varchar)

So that would make the following Good Variable names.

{a} {ab} {a.b} {a_b} {alpha.beta} {Answer_42}

{_}

{1_000_000} {%40ClientEndpoint}

and the following would be Bad Variable names.

{a b} {a..b} {alpha } { beta} {1,000,000}

The direction of RFC 6570 seems like a good start, but some of the things it seems to allow might complicate things.



 Comments   
Comment by markt_asf [ 19/Apr/13 10:16 PM ]

The limits from RFC6570 seem reasonable to me. Which ones do you think could be problematic?

Comment by dannycoward [ 23/Apr/13 10:38 PM ]

Hey there,

We are using level-1 templates only (e.g. see the spec document section 4.1.1). RFC6570 makes an unambiguous definition of what the legal characters are there.

Let me know if there are any ambiguities in the RFC6570 definition - Danny

Comment by joakimerdfelt [ 23/Apr/13 11:21 PM ]

RFC6570 has only 1 ambiguous part with how it relates to our JSR.

Section 2.3 - Variables
http://tools.ietf.org/html/rfc6570#section-2.3

variable-list = varspec *( "," varspec )
varspec = varname [ modifier-level4 ]
varname = varchar *( ["."] varchar )
varchar = ALPHA / DIGIT / "_" / pct-encoded

So that means, to the JSR, that @ServerEndpoint("/fruit/%40Type") would be allowed.
(My reading of level-1 variable names would be what 'varname' is defined like above)
However, when the @PathParam matching it up to the variable is concerned, do we follow the same 'varname' syntax as well? (this is not specified in section 4.3 of our JSR)
The declaration could be either @PathParam("%40Type") (leaving 'pct-encoded' alone)
or @PathParam("@Type") (decoded form of the pct-encoded)





[WEBSOCKET_SPEC-192] Use of Session (add|remove|get)MessageHandler from annotated endpoint Created: 18/Apr/13  Updated: 18/Apr/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: joakimerdfelt Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: gregwilkins and joakimerdfelt

 Description   

As reported on jsr356-experts:
http://java.net/projects/websocket-spec/lists/jsr356-experts/archive/2013-04/message/5

(snip)
If you have an annotated endpoint via @ClientEndpoint or @ServerEndpoint, can you use the various Session MessageHandler calls?

Session.addMessageHandler()

This would seem to makes sense, but the rules for replacing a "native websocket message type" should still apply, right?
So that if we have a @OnMessage annotated method with a TEXT type (such as String) then Session.addMessageHandler(MessageHandler.Whole<String>) shouldn't work.

Session.removeMessageHandler()

Should we be able to remove a @OnMessage annotated method?
Perhaps by exposing these annotated methods a implementation specific MessageHandlers?

Session.getMessageHandlers()

Should this also list the annotated @OnMessage methods as MessageHandlers?

It could be argued that it is confusing to have Session.addMessageHandler() fail with a reason that the the native websocket message type is already in use, but not have the means to remove the active one via removeMessageHandler(), or have the means to list them via getMessageHandlers().
(/snip)

This is another area needing clarification in the spec.

A proposal is to have to have the following methods not be available for Annotated WebSocket Endpoints.

Session.addMessageHandler()
Session.getMessageHandlers()
Session.removeMessageHandlers()

Throwing IllegalStateException when attempting to use them.



 Comments   
Comment by gregwilkins [ 18/Apr/13 10:44 PM ]

Is there really a need to allow ongoing add/remove of message handlers?

I would think that it is sufficient to have only add and to allow it only during a call to onOpen. After that, the handlers should be fixed and thus it does not matter if they are annotated or otherwise.

In cometd, we had a lot of problems with this kind of race - when we would notify an application of a new channel subscription which would often result in new message handlers being registered. If this is not made atomic, then it is always possible for messages to arrive before the message handler is registered. The solution in cometd was to have the mutable methods (eg addMessageHandler) only on a version of the interface that is only passed to the equivalent of onOpen.





[WEBSOCKET_SPEC-191] Endpoint.onOpen() and Session.addMessageHandler() race condition Created: 18/Apr/13  Updated: 24/Apr/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: joakimerdfelt Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: dannycoward, gregwilkins and joakimerdfelt

 Description   

As outlined in jsr356-experts:
http://java.net/projects/websocket-spec/lists/jsr356-experts/archive/2013-04/message/4

(snip)
A scenario for the group to ponder.
You have a ChatEndpoint extends Endpoint class.
WebSocket has been upgraded
Remote starts immediately sending text frames/messages.
Endpoint.onOpen(Session session, EndpointConfig config) is called.
ChatEndpoint.onOpen() performs a session.addMessageHandler(new ChatMessageHandler()) call.
If the implementation starts pushing those received messages as it gets them, then this gap of time between the open and session.addMessageHandler() can result in lost messages.

Is there a requirement in the spec somewhere that says processing of received messages should not start until the Endpoint.onOpen (or @OnOpen) call has completed?
Would seem to make sense.
(/snip)

This would also be another point of missing clarification in the current spec.



 Comments   
Comment by gregwilkins [ 18/Apr/13 10:39 PM ]

I would think that we should require that onOpen be called during the handshake processing and that the handshake reply should not be sent from the server until a successful return from onOpen. That way, if an exception is thrown in onOpen, the connection is no accepted.

Comment by dannycoward [ 23/Apr/13 06:49 PM ]

What the spec says is that each endpoint instance may only be called by one thread per client (e.g. section 5.1)

So in this scenario, the implementation is not supposed to deliver any messages to the endpoint until onOpen has completed.

So I guess the implementation will need to wait before processing anything coming in off the wire until the endpoint is ready. Or it could buffer anything that comes in too soon ?

As currently stated, the connection is supposed to be open before onOpen is called. I think this is consistent with JavaScript, for example, where developers can, for example, send messages from the onOpen callback.

Comment by joakimerdfelt [ 24/Apr/13 12:02 AM ]

Some thoughts.

onOpen should be called after the websocket connection has been established properly.
This is after a successful websocket handshake.

Sending messages from onOpen is a must.

Example scenario:

JSR WebSocket Client connects to server.
JSR WebSocket Client issues Upgrade.
WebSocket Server issues (in a single network buffer) the Upgrade response + a "Welcome" websocket TEXT message (complete, no continuations).
JSR WebSocket Client reads network buffer and issues onOpen to Client side socket.
It is at this point that the first "welcome" message should not be routed to the client socket until the onOpen is completed (without error).
[Note: An exception from onOpen results in an abnormal websocket close]
On completion of onOpen the first message is invoked, via any available message handler, to the client socket.

Note: a related issue, WEBSOCKET_SPEC-190, has a a comment from Greg Wilkins on proposes that onOpen be the only place MessageHandlers can be created. resulting in an immutable list of MessageHandlers after onOpen completes.

Comment by gregwilkins [ 24/Apr/13 02:46 AM ]

It is not really symmetrical between client and server. On the client, the receipt of the reply handshake is positive confirmation that the connection is open. On the server, there is no such positive confirmation, it only has the sending of the reply handshake without error that marks the opening of the endpoint.

So I agree that code in server side onOpen should be able to send messages, which means that either onOpen is called after sending the reply handshake or sent messages are queued. I think the former will result in simpler implementations, but we will need to define what happens if onOpen throws and exception (and I think closing with error is reasonable).

Also, as you say, the single threaded nature of endpoints also helps as it means that handlers added in onOpen will only be called after the onOpen return, which suggests that even if messages arrive before the call to addHandler, they will be handled by the addedHandler. So I think the spec can be interpreted without a race, but I think there is no harm being a bit more specific - something along the lines of: Handlers added during a call to onOpen will be used to handle all messages received, even those received during the call to onOpen and before the call to addHandler.

I think we should only allow calls to addHandler during onOpen, but if we are to allow them at other times, then we should probably make a similar statement about handlers added by another handler. ie if a handler replaces itself, then that will take effect for the next message, even if it was received before/during the call for the first message.





[WEBSOCKET_SPEC-190] MessageHandler collection change expectations Created: 18/Apr/13  Updated: 18/Apr/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: joakimerdfelt Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: gregwilkins and joakimerdfelt

 Description   

As reported on jsr356-experts here:
http://java.net/projects/websocket-spec/lists/jsr356-experts/archive/2013-04/message/3

(snip)
Question on expectations of MessageHandler collection changes.

Let me start by showing a scenario:
Endpoint is opened
Socket itself registers Session.addMessageHandler(new ChatMessageHandler()); // implements MessageHandler.Whole<String>
Incoming websocket frame. (op=TEXT, fin=false)
Implementation starts queuing up for whole message.
Incoming websocket frame. (op=CONTINUATION, fin=false)
Implementation appends frame for whole message.
Socket does Session.removeMessageHandler(chatMessageHandler);
Socket does Session.addMessageHandler(new EventMessageHandler()); // implements MessageHandler.Whole<String>
Incoming websocket frame. (op=CONTINUATION, fin=true)
Implementation appends frame for whole message.
Implementation notifies EventMessageHandler.onMessage(message); // Is this right?
The implementation would need to make a judgement call at #4 to say that the incoming TEXT frame is for a MessageHandler.Whole<String> and start queueing up the message. (otherwise for MessageHandler.Partial, it can start notifying the MessageHandler immediately)
However, when the implementation reaches step #11, the MessageHandler.Whole<String> has been swapped out.

Question is, should the implementation lock the TEXT MessageHandler at step #3 (initial frame of message) till it is called at step #11 (last frame of message)?
The PFD1 Javadoc for step #8 (Session.removeMessageHandler()) says that the remove should block until the handler is done processing and its no longer in use.

In short, I'm just trying to put some rules around the Session.addMessageHandler and Session.removeMessageHandler, along with making the usage of provided MessageHandlers consistent in a threading scenario.

One technique, would be to prevent altering the MessageHandler collection while in the middle of a websocket message. Only allowing changes between websocket messages.
But this seems like a recipe for a bad time with threading / dispatching / locks / etc ...

The technique Jetty has settled on, but we don't know if this is sane, is to pull from the MessageHandler collection at step #3 & 4 (initial incoming frame for the start of websocket message) and continue to use it for the rest of the message, making the MessageHandler collection itself not need any extra concurrency rules and eliminating the need to lock on step #7 and #8.

I am also working with a scenario where the Session starts with a MessageHandler.Partial and then gets swapped out for a MessageHandler.Whole. This means that I'll be treating a MessageHandler.Partial with the same rules for and entire websocket message. Once you start a websocket message, you continue to use the same MessageHandler for the entire message.

In our approach, the blocking requirement of Session.removeMessageHandler() is irrelevant. In our approach removing the MessageHandler is just an indication that future messages should not use this MessageHandler.

Is this a sane approach?
(/snip)

It would seem that the documentation around the add/remove of Message Handlers needs to be better.



 Comments   
Comment by gregwilkins [ 18/Apr/13 10:48 PM ]

This is kind of the same issue as http://java.net/jira/browse/WEBSOCKET_SPEC-191 and http://java.net/jira/browse/WEBSOCKET_SPEC-192 at least as much as all three can be solved by making the message handlers immutable after onOpen returns.





[WEBSOCKET_SPEC-184] ContainerProvider#getWebSocketContainer() has potential performance problems, needs caching Created: 16/Apr/13  Updated: 16/Apr/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: 1.0
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Nick Williams Assignee: Unassigned
Resolution: Unresolved Votes: 0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: Nick Williams

 Description   

Most other uses of the SPI system / `ServiceLoader` (read: every use I've ever seen) includes an underlying cache-by-classloader so that repeated calls do not perform badly. This comes in a form like this or similar:

public abstract class ContainerProvider {
    private static final WeakHashMap<ClassLoader, SoftReference<Iterable<ContainerProvider>>> CACHE = new WeakHashMap<>();

    public static WebSocketContainer getWebSocketContainer() {
        WebSocketContainer wsc = null;
        for (ContainerProvider impl : getProviders()) {
            wsc = impl.getContainer();
            if (wsc != null) {
                return wsc;
            }
        }
        if (wsc == null) {
            throw new RuntimeException("Could not find an implementation class.");
        } else {
            throw new RuntimeException("Could not find an implementation class with a non-null WebSocketContainer.");
        }
    }

    private Iterable<ContainerProvider> getProviders() {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        SoftReference<Iterable<ContainerProvider>> providers = CACHE.get(loader);
        if (providers != null && providers.get() != null) {
            return providers.get();
        }

        synchronized(CACHE) {
            providers = CACHE.get(loader);
            if (providers == null || providers.get() == null) {
                Set<ContainerProvider> set = new HashSet<>();
                for (ContainerProvider provider : ServiceLoader.load(ContainerProvider.class, loader)) {
                    set.add(provider);
                }
                providers = new SoftReference<>(set);
                CACHE.put(loader, providers);
            }
        }
        
        return providers.get();
    }
    ...
}

The ContainerProvider should have this caching mechanism. Calls to ContainerProvider#getWebSocketContainer() are expensive right now, and repeated calls will be an unnecessary drain on system resources.






[WEBSOCKET_SPEC-181] [jsr 356] java.lang.IllegalStateException: Not in 'deploy' scope Created: 05/Apr/13  Updated: 06/Aug/13

Status: Open
Project: websocket-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major
Reporter: jfarcand Assignee: Unassigned
Resolution: Unresolved Votes: 2
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags:
Participants: dannycoward, jfarcand, martin_grigorov and Pavel Bucek

 Description   

The following code:

public class JSR356AsyncSupport extends Servlet30CometSupport {
    public JSR356AsyncSupport(AtmosphereConfig config) {
        super(config);
        Object serverContainer = config.getServletContext().getAttribute("javax.websocket.server.ServerContainer");
        if (serverContainer != null) {
            try {
                ServerContainer.class.cast(serverContainer).addEndpoint(JSR356ServerEndpointConfig.class);
            } catch (DeploymentException e) {
                e.printStackTrace();
            }
        }
    }
}

produce

Caused by: java.lang.IllegalStateException: Not in 'deploy' scope.
	at org.glassfish.tyrus.servlet.TyrusServletServerContainer.addEndpoint(TyrusServletServerContainer.java:71)
	at org.atmosphere.container.JSR356AsyncSupport.<init>(JSR356AsyncSupport.java:29)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
	at org.atmosphere.cpr.DefaultAsyncSupportResolver.newCometSupport(DefaultAsyncSupportResolver.java:252)
	at org.atmosphere.cpr.DefaultAsyncSupportResolver.resolveWebSocket(DefaultAsyncSupportResolver.java:319)
	at org.atmosphere.cpr.DefaultAsyncSupportResolver.resolve(DefaultAsyncSupportResolver.java:307)
	at org.atmosphere.cpr.AtmosphereFramework.autoDetectContainer(AtmosphereFramework.java:1242)
	at org.atmosphere.cpr.AtmosphereFramework.init(AtmosphereFramework.java:567)
	at org.atmosphere.cpr.AtmosphereFramework.init(AtmosphereFramework.java:498)
	at org.atmosphere.cpr.AtmosphereServlet.init(AtmosphereServlet.java:195)
	at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1583)
	at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1382)
	at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5670)
	... 27 more

According to the Javadoc:

The ServerContainer is the specialized view of the WebSocketContainer available in server-side deployments. There is one ServerContainer instance per websocket application. The ServerContainer holds the methods to be able to register server endpoints during the initialization phase of the application.
For websocket enabled web containers, developers may obtain a reference to the ServerContainer instance by retrieving it as an attribute named javax.websocket.server.ServerContainer on the ServletContext. This way, the registration methods held on this interface may be called to register server endpoints from a ServletContextListener during the deployment of the WAR file containing the endpoint.

If you look at the stack trace, the servletContainer is retrieved during the Servlet.init() invocation.



 Comments   
Comment by Pavel Bucek [ 05/Apr/13 03:15 PM ]

hm, this probably needs to be clarified in the javadoc.

problem is in definition of scopes - this was intended to be called before init() invocation, so for example in ServletContextListener.

Comment by jfarcand [ 05/Apr/13 03:21 PM ]

Ya, I confirm it works inside a ServletContextListener.

But Tyrus is still completely broken because it can't deploy an Endpoint. A simple endpoint like:

    //@Override
    public Set<ServerEndpointConfig> getEndpointConfigs(Set<Class<? extends Endpoint>> endpointClasses) {
        logger.debug("{} detected.", JSR356ServerApplicationConfig.class.getName());
        return new HashSet<ServerEndpointConfig>() {{
            add(ServerEndpointConfig.Builder.create(JSR356Endpoint.class, "/*").configurator(new ServerEndpointConfig.Configurator() {
                public <T> T getEndpointInstance(java.lang.Class<T> endpointClass) throws java.lang.InstantiationException {
                    if (JSR356Endpoint.class.isAssignableFrom(endpointClass)) {
                        AtmosphereConfig config = BroadcasterFactory.getDefault().get("/*").getBroadcasterConfig().getAtmosphereConfig();
                        AtmosphereFramework f = config.framework();
                        return (T) new JSR356Endpoint(f, WebSocketProcessorFactory.getDefault().getWebSocketProcessor(f));
                    } else {
                        return super.getEndpointInstance(endpointClass);
                    }
                }

            }).build());
        }};
    }

   // @Override
    public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scanned) {
        return Collections.emptySet();
    }

will still fail to deploy. Can you make sure the programmatic API is tested (I don't see it in the unit test) before the release? I don't see any test in the Tyrus workspace. Thanks!

Comment by Pavel Bucek [ 05/Apr/13 03:26 PM ]

this is completely wrong

ServerEndpointConfig.Builder.create(JSR356Endpoint.class, "/*")
Comment by Pavel Bucek [ 05/Apr/13 03:30 PM ]

and we have plenty of tests related to programmatic API, please look again.

Comment by jfarcand [ 05/Apr/13 03:57 PM ]

replace /* with {path} and still it won't work.

Can you point me to the proper test?

Comment by jfarcand [ 05/Apr/13 03:59 PM ]

BTW I cannot test this since at Deployment ServerApplicationConfig aren't detected by GlassFish See issue #20195. That's why It's broken

Comment by Pavel Bucek [ 05/Apr/13 04:05 PM ]

see samples/programmatic-echo

I saw GLASSFISH-20195, but that unfortunately is not something I can fix right now..

Comment by dannycoward [ 10/Apr/13 12:12 AM ]

Hey Jeanfrancois - this programmatic deployment API wasn't ever supposed to work from servlet.init(). We're following the same model as the webcontainer does for deploying filters and servlets dynamically: you can do it up until the end of ServletContext initialization, e.g.

http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContext.html#addFilter%28java.lang.String,%20javax.servlet.Filter%29

but not after.

I think this means that you are guaranteed to be able to do it from a SCI, or from a ServletContextListener. But (this is my understanding) servlets themselves do not have to have their init()s called in this period. They might never be called if no-one asks for the URL its mapped to !

  • Danny
Comment by martin_grigorov [ 05/Aug/13 11:04 AM ]

Is it possible to allow registering endpoints in Filter#init() implementation ?
Apache Tomcat 8.x allows it and this makes it much easier for integration with web frameworks.

For example Apache Wicket frameworks configures itself by using Servlet Filter. To be able to support WebSocket on Glassfish we will have to require our users to add more stuff in web.xml.

Comment by martin_grigorov [ 06/Aug/13 07:01 AM ]

Here is a link to the issue in Tomcat's tracker that made it possible to add endpoints in later phase: https://issues.apache.org/bugzilla/show_bug.cgi?id=55314

As web framework developer I find this functionality as very useful.





Generated at Thu Apr 24 11:11:06 UTC 2014 using JIRA 4.0.2#472.