Хобрук: Ваш путь к мастерству в программировании

как использовать объект, введенный с помощью @Inject в метод @OnOpen конечных точек сервера

У меня есть Bean, который создает экземпляр объекта, который мне нужно внедрить в другие bean-компоненты. Все работает нормально, я могу распечатать свойство введенного объекта в методе @PostConstruct, но если я попытаюсь вызвать метод из этого введенного объекта внутри метода @OnOpen ServerEndpoint, это даст мне исключение NullPointerException.

Вот моя конечная точка сервера

@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, причал 9.1, jsf 2.2, java-ee7 и веб-сокеты от java-ee7

21.07.2014

  • Какую реализацию веб-сокета вы используете? атмосфера? Какой фреймворк? какой сервер? стеклянная рыба? причал? 21.07.2014
  • Мое объяснение состоит в том, что bean-компонент, созданный cdi, отличается от bean-компонента, созданного контейнером веб-сокетов, поскольку веб-сокеты создаются только тогда, когда запрашивается соединение. Попробуйте, вероятно, изменить bean-компонент с applicationscoped на sessionscoped. 21.07.2014

Ответы:


1

Проблема в том, что BeanThree объявляется одновременно и компонентом CDI, и конечной точкой. Он должен быть разделен на два разных компонента:

@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 и связанными с сеансом данными. Вот пример.

21.07.2014

2

Один из способов сделать это — разрешить CDI создавать его экземпляр как компонент CDI.

Затем создает подклассы следующих классов: 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

21.07.2014
  • Можете ли вы уточнить, как выполнить поиск cdi? 21.07.2014
  • См. ссылку на обновленный вопрос о том, как получить ссылку на beanmanager. 22.07.2014
  • В CDI 1.1/1.2 проще выполнять поиск вручную - CDI.current().select(Class beanClass, Annotation...annotations).get() 24.07.2014
  • Новые материалы

    Создание кнопочного меню с использованием HTML, CSS и JavaScript
    Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

    Внедрите OAuth в свои веб-приложения для повышения безопасности
    OAuth — это широко распространенный стандарт авторизации, который позволяет приложениям получать доступ к ресурсам от имени пользователя, не раскрывая его пароль. Это позволяет пользователям..

    Классы в JavaScript
    class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

    Как свинг-трейдеры могут использовать ИИ для больших выигрышей
    По мере того как все больше и больше профессиональных трейдеров и активных розничных трейдеров узнают о возможностях, которые предоставляет искусственный интеллект и машинное обучение для улучшения..

    Как построить любой стол
    Я разработчик программного обеспечения. Я люблю делать вещи и всегда любил. Для меня программирование всегда было способом создавать вещи, используя только компьютер и мое воображение...

    Обзор: Машинное обучение: классификация
    Только что закончил третий курс курса 4 часть специализации по машинному обучению . Как и второй курс, он был посвящен низкоуровневой работе алгоритмов машинного обучения. Что касается..

    Разработка расширений Qlik Sense с qExt
    Использование современных инструментов веб-разработки для разработки крутых расширений Вы когда-нибудь хотели кнопку для установки переменной в приложении Qlik Sense? Когда-нибудь просили..