[WEBSOCKET_SPEC-165] Difficulty implementing ServerContainer bootstrap portably on the web container Created: 07/Mar/13 Updated: 21/Mar/13 Resolved: 21/Mar/13
|Remaining Estimate:||Not Specified|
|Time Spent:||Not Specified|
|Original Estimate:||Not Specified|
There doesn't yet seem to be a way to ensure that the instance of ServerContainer returned from the ServerContainerProvider is the unique instance associated with the application where the call is made.
There have been a few suggestions as to how to do this, from using thread local, to adding the ServletContext as a parameter to the bootstrap call, to keying the instance by the context root. The latter two only work on web containers; this mechanism was also supposed to work elagantly for standalone containers.
We may leave this as a container specific mechanism for 1.0. We will gather more information from implementations before deciding whether this has to be addressed for version 1.0.
|Comment by markt_asf [ 07/Mar/13 ]|
I've looked at trying to get the ServletContext from the class loader and while the container has that mapping internally it is not currently exposed. I'd have to make some changes to Tomcat to enable the WebSocket to get to it and I'm not overly keen on that.
I think there are three options:
1. Do something container specific to find the ServletContext.
2. ServerContainer.setContext(Object ctxt)
3. ServerContainerProvider.getServerContainer(Object ctxt)
I don't like 1 for several reasons. Primarily because it is container specific and it would make a container neutral WebSocket implementation impossible. I know container neutrality isn't currently a formal requirement but at the moment there is nothing that requires a container specific approach. I would very much prefer to keep it that way.
Tomcat currently uses 2. On the plus side this method only needs to be called in a 100% programmatic case as the SCI can call it in all other cases. That keeps things simple for the developer and the implementation can throw an exception if it isn't set in the 100% programmatic case. The downside is that it still relies on the current class loader to map to the correct ServletContext. That is potentially fragile since the current class loader may not be the web application class loader in all cases. There are likely to be ways around this but it adds some complexity. The other advantage of 2 is that it can easily be added to the API at a later date if we don't add it now.
Option 3 has the advantage of not needing to use the class loader to map to the ServletContext but the price is that every call must provide a ServletContext. That may cause complications in some use cases if the ServletContext isn't easily available. The other downside is that adding this to the spec later would mean (potentially) deprecating the current method and adding this new one.
My preference is for 2 or 3 with perhaps a slight leaning towards 2.
|Comment by dannycoward [ 07/Mar/13 ]|
Something we're going to do in Tyrus is make sure there is a strong association between the servlet context instance for the application and the server container instance for the application. We think that association can be made portably on top of the servlet container by associating the two inside a ServletContainerInitializer packaged in the Tyrus module, since it is called before any application ServletContextListeners or web components are called.
Once we have that, 2 and 3 are pretty trivial to implement (and there are other choices too - I think an older idea of using the context root is another rendition). No need to rely on container specific mechanisms to do with classloaders or thread.local.
I think the use case on the web container means that the developer is always calling this from code which has access to the ServletContext instance for the application, so that's ok.
In the standalone case, I think implementations will need to provide the server container instance as part of their (proprietary) startup mechanism - like public void start(ServerContainer instance) or something.
|Comment by dannycoward [ 21/Mar/13 ]|
We will remove the ServerContainerProvider and make the ServerContainer instance available as a ServletContext attribute.