jsr356-experts@websocket-spec.java.net

[jsr356-experts] Re: Controlling endpoint instance creation was: Two outstanding issues...

From: Joakim Erdfelt <joakim_at_intalio.com>
Date: Mon, 25 Feb 2013 20:29:39 -0700

Be sure that the ServerEndPointConfigurator has clear documentation about
how the 3 websocket creation flow methods relate (and order that they
appear)

boolean checkOrigin(String originHeaderValue)
void modifyHandshake(ServerEndpointConfiguration sec, HandshakeRequest
request, HandshakeResponse response)
Object createEndpoint();

Some of the desires expressed about programmatic endpoint creation..

   1. Ability to create arbitrary endpoints (either from implementations of
   Endpoint or from annotated objects)
      1. This means that the developer might choose to provide the same
      Endpoint instance to many incoming websocket upgrade requests
and just use
      the stateless form annotations with the Session object to handle
responses.
      Implementations of this JSR must be able to handle this scenario.
   2. Ability to create endpoints based on information present in
   HandshakeRequest and HandshakeResponse
      1. Request Path
      2. Request Query Parameters
      3. Requested SubProtocol List
      4. Arbitrary Request Headers
      5. Based on Created Endpoint, supply HandshakeResponse subprotocol
      6. Ability to fail Websocket Upgrade if createEndpoint() is not
      possible (keep in mind this also means controlling the HTTP Response Code)


--
Joakim Erdfelt <joakim_at_intalio.com>
webtide.com <http://www.webtide.com/>
Developer advice, services and support
from the Jetty & CometD experts
eclipse.org/jetty - cometd.org
On Mon, Feb 25, 2013 at 5:42 PM, Danny Coward <danny.coward_at_oracle.com>wrote:
>  OK, well several of you have voiced a desire for this need to control
> creation of instances, I think our ServerEndpointConfigurator could be
> extended to play the role and provide the hook.
>
> If all of you that want this are ok with just using the CDI:
> javax.annotation.PostConstruct annotation, then please speak up and we are
> done ! But I strongly suspect not, so otherwise, please read on:-
>
> The 'EndpointFactory' proposal would be to add what was the old (from
> v008!) EndpointFactory.create() method for endpoint instances to todays
> ServerEndpointConfigurator.
>
> The developer can already provide a customized ServerEndpointConfigurator
> by subtyping it, overriding any of its methods and either setting it in the
> ServerEndpointConfigurationBuilder, or by using the configuration()
> attribute in @ServerEndpoint.
>
> So if we add the factory method there, the developer can provide his own
> implementation of the method. The specification would require that this
> method be used if overridden. The container default
> ServerEndpointConfigurator would use its existing mechanisms to instantiate
> the endpoint instances (i.e. using CDI in the EE case, public no-arg
> constructor else).
>
> Specifically, add to ServerEndpointConfigurator
>
> /** (something like) This method is called by the container when it needs
> a new
> ** instance of the endpoint this configurator configures. Developers
> ** may override this method to control instantiation of
> ** endpoint instances in order to customize the initialization
> ** of the endpoint instance, or manage them in some other way.
> ** If the developer overrides this method, services like
> ** dependency injection that are otherwise supported
> ** may not be available.
> */
> public Object createEndpoint() throws InstantiationException;
>
> Works equally well for programmatic endpoints and annotated endpoints, and
> fits with the existing configuration scheme.
>
> - Danny
>
>
>
>
>
> On 2/25/13 9:09 AM, Scott Ferguson wrote:
>
> On 2/25/13 6:27 AM, Joe Walnes wrote:
>
> I'll just pipe up and say that I'm still a big supporter of the
> EndpointFactory approach ;).
>
>  On the hybrid thing, I don't see it as too complicated: All Endpoints
> always get constructed through an EndpointFactory, and we include some
> standard implementations for the default mechanism. Most users will
> probably just leave the default in place, but for those who need their own
> control of construction (could be manual, could be through a 3rd party DI
> library), the hook is there for them without adding too much complexity.
>
>  It also folds into the other issue... we could defer the singleton
> question until .next, but users who want it now can do it themselves with a
> custom EndpointFactory implementation.
>
>
> I basically agree.
>
> Another alternative is the older "launch websockets from a normal servlet"
> style, which has a side benefit of allowing encapsulation of anything
> available to a normal servlet. In Resin's early websocket design, we used
> something similar to the client publish:
>
>   @Inject
>   private WebSocketServletContainer container; ... [obtained somehow if
> CDI isn't available]
>
>   public void service(ServletRequest req, ServletResponse res)
>   {
>      Endpoint myEndpoint = ...;
>
>      wsSession = container.startWebSocketEndpoint(req, res, myEndpoint);
>   }
>
> Possible benefits:
>   1. "myEndpoint" can be instantiated however the application wants,
> including a singleton
>   2. it can encapsulate anything available to a servlet (including the
> session or auth/login/user info)
>   3. allows for dynamic launching (i.e. not fixed URLs)
>
> -- Scott
>
>
>
>
>
>
>
>
>
>
>  cheers
> -Joe
>
>
> On Thu, Feb 21, 2013 at 5:58 PM, Danny Coward <danny.coward_at_oracle.com>wrote:
>
>>  Hi folks,
>>
>> Two last issues from the JIRA that we have not yet covered: bringing back
>> the EndpointFactory, and deploying server endpoints so that only one
>> instance per path is used, rather than a new instance per client.
>>
>> 1) Bringing back the EndpointFactory
>>
>> Joe posted about the EndpointFactory in detail (
>> http://java.net/projects/websocket-spec/lists/jsr356-experts/archive/2013-01/message/2),
>> and we didn't have much discussion about it at the time, but I did log it.
>> Essentially, the EndpointFactory idea allows developer provided code to be
>> run to produce the endpoint instance. So any endpoint instance
>> configuration can happen there. In the *Configuration model we have now,
>> such configuration code has to be located in a developer provided
>> *Configurator class.
>>
>> My own take is that the world of injection frameworks really requires us
>> to allow the containers to instantiate these endpoints, their use is more
>> and more common. While we could absolutely have a hybrid model where if you
>> are not in a DI environment you could supply a factory, and if you are in a
>> DI world you use something like a configurator, I think two models would be
>> just too complicated.
>>
>> We would also still need something like the Configurator if we had
>> EndpointFactory. And we would need the Configuation classes. So, the
>> EndpointFactory approach leads us to a bigger API :(
>>
>> I think functionally, the approaches are equivalent, even if one is the
>> 'inside out' version of the other Factory.create() versus endpoint.onOpen().
>>
>> I think the new configuration apis do address some of the concerns forced
>> by the public no-arg constructor on Endpoint: we have a property bag on the
>> EndpointConfiguration interface for easier sharing of data across instances
>> without having to subtype. We have also de-coupled the Endpoint and the
>> EndpointConfiguration in the newer API: now the same Endpoint class can be
>> deployed in multiple configurations (say, URIs) because the deployment of
>> an Endpoint is done with an EndpointConfiguration instance instead of class.
>>
>> So, not a perfect answer at all for our custom configuration example, but
>> I think a simpler solution overall not to try to bring back the
>> EndpointFactory.
>>
>> Are there any big supporters of the endpoint factory approach ?
>>
>>
>> 2) Allow deployment of server endpoint singletons.
>>
>> The Endpoint API certainly allows for this kind of case where the
>> developer wants a single instance to handle all connections, instead of
>> today's (simpler) model where a new instance is created per connection.
>> You'll probably remember that at first the spec defined endpoint to be
>> singletons, then we decided to opt for the easier single threaded 'one per
>> client' endpoint model because we thought that would make for an easier
>> development model for the more common use cases.
>>
>> Now, all the lifecycle methods take the Session, so the connections can
>> all be disambiguated.  Such 'singleton' endpoints would be different from
>> today's 'one per client' endpoints. They would need to be programmed for
>> concurrent incoming events/messages from different clients. The 'singleton'
>> endpoints operate in the context of multiple session objects, the 'one per
>> client' endpoints operate in the context of just one. So, it seems to me,
>> except in the most trivial cases, they are likely to be programmed quite
>> differently, even if they both fit into the Endpoint model.
>>
>> All of which makes me think that we should be distinguishing these two
>> types of server endpoint more formally. Perhaps extended API, perhaps more
>> meta data in the annotations.
>>
>> Which makes me think we should play it safe, stick with the 'one instance
>> per client' model we have, and look at singletons in more detail in .next.
>>
>> Are there any big supporters of the singleton approach ?
>>
>> Thanks,
>>
>> - Danny
>>
>> --
>>   <http://www.oracle.com> * Danny Coward *
>>  Java EE
>> Oracle Corporation
>>
>
>
>
>
> --
>   <http://www.oracle.com> * Danny Coward *
>  Java EE
> Oracle Corporation
>