如何在服务器端点@OnOpen方法中使用@Inject注入的Object

时间:2014-07-21 10:29:28

标签: java java-ee cdi

我有一个Bean,它创建一个对象的实例,我需要将其注入其他bean。一切正常,我可以在@PostConstruct方法中打印注入对象的属性,但是如果我尝试从ServerEndpoint的@OnOpen方法中的注入对象中调用一个方法,它会给我一个NullPointerException。

这是我的ServerEndpoint

@Named
@ApplicationScoped
@ServerEndpoint(value = "/websocket")
public class BeanThree {
    private String message = "test";
    @Inject private User user;

    @PostConstruct
    public void init() { System.out.println(user.getUserName()); } <-- displayed in the console correctly
    public String getMessage() { return this.message; }

    @OnOpen
    public void onOpen(Session session) {
        System.out.println("onOpen");
        System.out.println(user.getUserName()); <-- causes NullPointerException
    }
}

有可能解决这个问题吗?

EDIT1: 我使用cdi 1.2,jetty 9.1,jsf 2.2,java-ee7和来自java-ee7的websockets

2 个答案:

答案 0 :(得分:4)

问题是BeanThree同时被声明为CDI bean和端点。 它必须分成两个不同的bean:

@ServerEndpoint("/endpoint")
public class BeanThree {
    @Inject
    ApplicationScopedBean bean;

    @OnOpen
    public String onOpen(Session s) { System.out.println(bean); }
    @OnMessage
    public String onMessage(String message) { System.out.println(bean); }
}
@ApplicationScoped
public class ApplicationScopedBean { ... }

但还有另一个问题 CDI / Websocket集成非常有限:开箱即用,您只能注入@ApplicationScoped@Dependent个bean。
从您的代码段开始,您似乎打算使用@SessionScoped User bean进行Websocket会话。这不会起作用,因为Websocket和HTTP会话不同 您必须自己管理Websocket会话和会话绑定数据。这是一个example

答案 1 :(得分:1)

这样做的一种方法是允许CDI将其实例化为CDI bean。

然后对以下类进行子类化:ServerEndpointConfig.Configurator

@ServerEndpoint(..., configurator=MyCustomConfigurator.class)
@SessionScoped
@Named("myMessageHandler")
public class MyMessageHandler{

 @Inject
 private MyInjectable instance;

 ...
}

public class MyCustomConfigurator extends ServerEndpointConfig.Configurator{
  public <T extends Object> getEndpointInstance(Class<T> endpointClass) throws InstantiationException{
  //do cdi lookup for endpoint using the simple name.
}

要获得对cdi BeanManager的引用,请查看此线程: http://dominikdorn.com/2010/04/cdi-weld-manual-bean-lookup/

在你的情况下,你没有对FacesContext的引用,所以使用ServletContext