@ServerEndpoint Guice

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

@ServerEndpoint Guice

Marko Sanković
Hi,

For the last couple of hours I've been trying to inject a simple object
into the class that is @ServerEndpoint annotated.

As stated: Tomcat implements the Java WebSocket 1.0 API defined by JSR-356.

I'm using Guice as dependency injection framework and Tomcat 7.0.47.

This is how my websocket server endpoint looks like:

...
import com.google.inject.Inject;
...
@ServerEndpoint("/wsendpoint")
public class WsEndpoint {

    @Inject
    InjectedSimpleBean injectedSimpleBean;

    ...
}

I can connect to this endpoint, send and receive messages, but
injectedSimpleBean attribute is null (as expected).

I guess I will have to change the
way java/org/apache/tomcat/websocket/server/DefaultServerEndpointConfigurator.java
instantiates endpoint class, the getEndpointInstace method will have to
call something like:

injector.getInstance(clazz);

but, then again the DefaultServerEndpointConfiguration will also have be
instantiated by the injector.

Any help would be appreciated. Thanks
Reply | Threaded
Open this post in threaded view
|

Re: @ServerEndpoint Guice

Nick Williams-4

On Nov 6, 2013, at 7:55 AM, Marko Sanković wrote:

> Hi,
>
> For the last couple of hours I've been trying to inject a simple object
> into the class that is @ServerEndpoint annotated.
>
> As stated: Tomcat implements the Java WebSocket 1.0 API defined by JSR-356.
>
> I'm using Guice as dependency injection framework and Tomcat 7.0.47.
>
> This is how my websocket server endpoint looks like:
>
> ...
> import com.google.inject.Inject;
> ...
> @ServerEndpoint("/wsendpoint")
> public class WsEndpoint {
>
>    @Inject
>    InjectedSimpleBean injectedSimpleBean;
>
>    ...
> }
>
> I can connect to this endpoint, send and receive messages, but
> injectedSimpleBean attribute is null (as expected).
>
> I guess I will have to change the
> way java/org/apache/tomcat/websocket/server/DefaultServerEndpointConfigurator.java
> instantiates endpoint class, the getEndpointInstace method will have to
> call something like:
>
> injector.getInstance(clazz);
>
> but, then again the DefaultServerEndpointConfiguration will also have be
> instantiated by the injector.
>
> Any help would be appreciated. Thanks

Changing the Tomcat-specific class won't be necessary. You can do this with just the API. In your @ServerEndpoint annotation, you need to specify a different configuration that extends javax.websocket.server.ServerEndpointConfig.Configurator. Spring Framework has a class [1] that does just this for its DI and other bean processing. You can probably create a class modeled after that.

Nick

[1] https://github.com/spring-projects/spring-framework/blob/master/spring-websocket/src/main/java/org/springframework/web/socket/server/endpoint/SpringConfigurator.java?source=cc
---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: @ServerEndpoint Guice

Marko Sanković
Nick, thanks for your quick response.

Unfortunately, specifying javax.websocket.server.ServerEndpointConfig.
Configurator is still not enough. This is what I have tried so far:

@ServerEndpoint(value = "/wsendpoint", configurator =
WsEndpointConfigurator.class)
public class WsEndpoint {
    @Inject
    InjectedSimpleBean injectedSimpleBean;
    ...
}

and the WsEndpointConfigurator.java:

public class WsEndpointConfigurator extends Configurator {

    @Inject
    Injector injector;

    @Override
    public <T> T getEndpointInstance(Class<T> endpointClass)
            throws InstantiationException {
        return (T) injector.getInstance(endpointClass);
    }
}

As expected attribute injector is null. To my understanding configurator
has to be instantiated through guice, same for the class that instantiates
configurator (ServerEndpointConfig). How can I do that?

Tyrus has the sample of what I really need:
https://tyrus.java.net/documentation/1.3/user-guide.html#d0e1075. In my
case, I have to achieve that with Google Guice and Tomcat 7.0.47.

Thanks





On 6 November 2013 16:23, Nick Williams <[hidden email]>wrote:

>
> On Nov 6, 2013, at 7:55 AM, Marko Sanković wrote:
>
> > Hi,
> >
> > For the last couple of hours I've been trying to inject a simple object
> > into the class that is @ServerEndpoint annotated.
> >
> > As stated: Tomcat implements the Java WebSocket 1.0 API defined by
> JSR-356.
> >
> > I'm using Guice as dependency injection framework and Tomcat 7.0.47.
> >
> > This is how my websocket server endpoint looks like:
> >
> > ...
> > import com.google.inject.Inject;
> > ...
> > @ServerEndpoint("/wsendpoint")
> > public class WsEndpoint {
> >
> >    @Inject
> >    InjectedSimpleBean injectedSimpleBean;
> >
> >    ...
> > }
> >
> > I can connect to this endpoint, send and receive messages, but
> > injectedSimpleBean attribute is null (as expected).
> >
> > I guess I will have to change the
> > way
> java/org/apache/tomcat/websocket/server/DefaultServerEndpointConfigurator.java
> > instantiates endpoint class, the getEndpointInstace method will have to
> > call something like:
> >
> > injector.getInstance(clazz);
> >
> > but, then again the DefaultServerEndpointConfiguration will also have be
> > instantiated by the injector.
> >
> > Any help would be appreciated. Thanks
>
> Changing the Tomcat-specific class won't be necessary. You can do this
> with just the API. In your @ServerEndpoint annotation, you need to specify
> a different configuration that extends
> javax.websocket.server.ServerEndpointConfig.Configurator. Spring Framework
> has a class [1] that does just this for its DI and other bean processing.
> You can probably create a class modeled after that.
>
> Nick
>
> [1]
> https://github.com/spring-projects/spring-framework/blob/master/spring-websocket/src/main/java/org/springframework/web/socket/server/endpoint/SpringConfigurator.java?source=cc
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>
Reply | Threaded
Open this post in threaded view
|

Re: @ServerEndpoint Guice

Nick Williams-4

On Nov 6, 2013, at 4:24 PM, Marko Sanković wrote:

> Nick, thanks for your quick response.
>
> Unfortunately, specifying javax.websocket.server.ServerEndpointConfig.
> Configurator is still not enough. This is what I have tried so far:
>
> @ServerEndpoint(value = "/wsendpoint", configurator =
> WsEndpointConfigurator.class)
> public class WsEndpoint {
>    @Inject
>    InjectedSimpleBean injectedSimpleBean;
>    ...
> }
>
> and the WsEndpointConfigurator.java:
>
> public class WsEndpointConfigurator extends Configurator {
>
>    @Inject
>    Injector injector;
>
>    @Override
>    public <T> T getEndpointInstance(Class<T> endpointClass)
>            throws InstantiationException {
>        return (T) injector.getInstance(endpointClass);
>    }
> }
>
> As expected attribute injector is null. To my understanding configurator
> has to be instantiated through guice, same for the class that instantiates
> configurator (ServerEndpointConfig). How can I do that?
>
> Tyrus has the sample of what I really need:
> https://tyrus.java.net/documentation/1.3/user-guide.html#d0e1075. In my
> case, I have to achieve that with Google Guice and Tomcat 7.0.47.
>
> Thanks

Marko,

Guice is not going to be able to instantiate your WsEndpointConfigurator, so you cannot have your Injector injected. The same problem exists with Spring's SpringConfigurator. The container, not the framework, instantiates it. The solution is to call some static method to "look up" the injector. For SpringConfigurator, that means calling ContextLoader.getCurrentWebApplicationContext() and using the returned ApplicationContext to instantiate the endpoint. I do not know what the equivalent is in Guice because I have never used Guice before. However, I'm sure Guice has something similar. It wouldn't be very flexible if it didn't.

Nick

>
> On 6 November 2013 16:23, Nick Williams <[hidden email]>wrote:
>
>>
>> On Nov 6, 2013, at 7:55 AM, Marko Sanković wrote:
>>
>>> Hi,
>>>
>>> For the last couple of hours I've been trying to inject a simple object
>>> into the class that is @ServerEndpoint annotated.
>>>
>>> As stated: Tomcat implements the Java WebSocket 1.0 API defined by
>> JSR-356.
>>>
>>> I'm using Guice as dependency injection framework and Tomcat 7.0.47.
>>>
>>> This is how my websocket server endpoint looks like:
>>>
>>> ...
>>> import com.google.inject.Inject;
>>> ...
>>> @ServerEndpoint("/wsendpoint")
>>> public class WsEndpoint {
>>>
>>>   @Inject
>>>   InjectedSimpleBean injectedSimpleBean;
>>>
>>>   ...
>>> }
>>>
>>> I can connect to this endpoint, send and receive messages, but
>>> injectedSimpleBean attribute is null (as expected).
>>>
>>> I guess I will have to change the
>>> way
>> java/org/apache/tomcat/websocket/server/DefaultServerEndpointConfigurator.java
>>> instantiates endpoint class, the getEndpointInstace method will have to
>>> call something like:
>>>
>>> injector.getInstance(clazz);
>>>
>>> but, then again the DefaultServerEndpointConfiguration will also have be
>>> instantiated by the injector.
>>>
>>> Any help would be appreciated. Thanks
>>
>> Changing the Tomcat-specific class won't be necessary. You can do this
>> with just the API. In your @ServerEndpoint annotation, you need to specify
>> a different configuration that extends
>> javax.websocket.server.ServerEndpointConfig.Configurator. Spring Framework
>> has a class [1] that does just this for its DI and other bean processing.
>> You can probably create a class modeled after that.
>>
>> Nick
>>
>> [1]
>> https://github.com/spring-projects/spring-framework/blob/master/spring-websocket/src/main/java/org/springframework/web/socket/server/endpoint/SpringConfigurator.java?source=cc
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: @ServerEndpoint Guice

Marko Sanković
Nick,

Thank you once again. In a servlet injector can be accessed through
getServletContext.getAttribute("Injector")

As you said, I had to implement static method that returns instance of
injector and use it in my EndpointConfiguration to instantiate
ServerEndpoint. This is what I have done:

// The listener installs Guice modules through GuiceServletConfigFactory

public class GuiceServletConfig extends GuiceServletContextListener {
  @Override    protected Injector getInjector() {        return
GuiceServletConfigFactory.getInjector();    }}


// GuiceServletConfigFactory has static method that returns instance of
injector

public class GuiceServletConfigFactory {    private static final
Injector injector = Guice.createInjector(            new
ServerModule(), new DispatchServletModule());    public static
Injector getInjector() {        return injector;    }}


// ServerEndpoint uses WsEndpointConfiguration to instantiate it

@ServerEndpoint(value = "/wsendpoint", configurator =
WsEndpointConfigurator.class, decoders =
JsonRPCRequestDecoder.class)public class WsEndpoint { ... }


// WsEndpointConfiguration can access injector and use it to instantiate
ServerEndpoint class

public class WsEndpointConfigurator extends Configurator {
@Override    public <T> T getEndpointInstance(Class<T> endpointClass)
          throws InstantiationException {        return (T)
GuiceServletConfigFactory.getInjector().getInstance(
endpointClass);    }}


The full source code: https://bitbucket.org/markosankovic/wsgwtp

On 7 November 2013 16:44, Nick Williams <[hidden email]>wrote:

>
> On Nov 6, 2013, at 4:24 PM, Marko Sanković wrote:
>
> > Nick, thanks for your quick response.
> >
> > Unfortunately, specifying javax.websocket.server.ServerEndpointConfig.
> > Configurator is still not enough. This is what I have tried so far:
> >
> > @ServerEndpoint(value = "/wsendpoint", configurator =
> > WsEndpointConfigurator.class)
> > public class WsEndpoint {
> >    @Inject
> >    InjectedSimpleBean injectedSimpleBean;
> >    ...
> > }
> >
> > and the WsEndpointConfigurator.java:
> >
> > public class WsEndpointConfigurator extends Configurator {
> >
> >    @Inject
> >    Injector injector;
> >
> >    @Override
> >    public <T> T getEndpointInstance(Class<T> endpointClass)
> >            throws InstantiationException {
> >        return (T) injector.getInstance(endpointClass);
> >    }
> > }
> >
> > As expected attribute injector is null. To my understanding configurator
> > has to be instantiated through guice, same for the class that
> instantiates
> > configurator (ServerEndpointConfig). How can I do that?
> >
> > Tyrus has the sample of what I really need:
> > https://tyrus.java.net/documentation/1.3/user-guide.html#d0e1075. In my
> > case, I have to achieve that with Google Guice and Tomcat 7.0.47.
> >
> > Thanks
>
> Marko,
>
> Guice is not going to be able to instantiate your WsEndpointConfigurator,
> so you cannot have your Injector injected. The same problem exists with
> Spring's SpringConfigurator. The container, not the framework, instantiates
> it. The solution is to call some static method to "look up" the injector.
> For SpringConfigurator, that means calling
> ContextLoader.getCurrentWebApplicationContext() and using the returned
> ApplicationContext to instantiate the endpoint. I do not know what the
> equivalent is in Guice because I have never used Guice before. However, I'm
> sure Guice has something similar. It wouldn't be very flexible if it didn't.
>
> Nick
>
> >
> > On 6 November 2013 16:23, Nick Williams <[hidden email]
> >wrote:
> >
> >>
> >> On Nov 6, 2013, at 7:55 AM, Marko Sanković wrote:
> >>
> >>> Hi,
> >>>
> >>> For the last couple of hours I've been trying to inject a simple object
> >>> into the class that is @ServerEndpoint annotated.
> >>>
> >>> As stated: Tomcat implements the Java WebSocket 1.0 API defined by
> >> JSR-356.
> >>>
> >>> I'm using Guice as dependency injection framework and Tomcat 7.0.47.
> >>>
> >>> This is how my websocket server endpoint looks like:
> >>>
> >>> ...
> >>> import com.google.inject.Inject;
> >>> ...
> >>> @ServerEndpoint("/wsendpoint")
> >>> public class WsEndpoint {
> >>>
> >>>   @Inject
> >>>   InjectedSimpleBean injectedSimpleBean;
> >>>
> >>>   ...
> >>> }
> >>>
> >>> I can connect to this endpoint, send and receive messages, but
> >>> injectedSimpleBean attribute is null (as expected).
> >>>
> >>> I guess I will have to change the
> >>> way
> >>
> java/org/apache/tomcat/websocket/server/DefaultServerEndpointConfigurator.java
> >>> instantiates endpoint class, the getEndpointInstace method will have to
> >>> call something like:
> >>>
> >>> injector.getInstance(clazz);
> >>>
> >>> but, then again the DefaultServerEndpointConfiguration will also have
> be
> >>> instantiated by the injector.
> >>>
> >>> Any help would be appreciated. Thanks
> >>
> >> Changing the Tomcat-specific class won't be necessary. You can do this
> >> with just the API. In your @ServerEndpoint annotation, you need to
> specify
> >> a different configuration that extends
> >> javax.websocket.server.ServerEndpointConfig.Configurator. Spring
> Framework
> >> has a class [1] that does just this for its DI and other bean
> processing.
> >> You can probably create a class modeled after that.
> >>
> >> Nick
> >>
> >> [1]
> >>
> https://github.com/spring-projects/spring-framework/blob/master/spring-websocket/src/main/java/org/springframework/web/socket/server/endpoint/SpringConfigurator.java?source=cc
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: [hidden email]
> >> For additional commands, e-mail: [hidden email]
> >>
> >>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>