2016-12-15 6 views
1

У меня возникли некоторые проблемы с доступом к экземпляру PushContext.Доступ к экземпляру OmniFaces PushContext в потоке, который выполняется отдельно от управляемого компонента

Я бы хотел послать сообщения внутри потока, который выполняется отдельно от управляемого компонента. При введении через @Injected @Push я не могу. Кто-нибудь знает, как я могу это сделать?

ответ

1

Доступ к экземпляру OmniFaces PushContext в потоке

PushContext может быть введен только в контейнер управляемого артефакт, проживающих в WAR (например @Named, @WebServlet, @WebFilter, @WebListener, и т.д.), а не в других местах (т.е. абсолютно не в @Stateless, @Stateful, @Singleton и т. д.).

Я хотел бы послать сообщения внутри потока, который проходит отдельно от управляемого компонента

Это будет работать только если поток управляется контейнером, например, как один инициированной EJB's @Asynchronous. Он не будет работать, если поток неуправляем (т. Е. Вручную создается с использованием Thread). Это подробно объясняется в Is it safe to start a new thread in a JSF managed bean?

При правильном использовании EJB @Asynchronous, просто следуйте приведенным ниже примерам в документации <o:socket>. Вы можете найти их в разделе EJB design hints.

Ниже выдержка из documentation показывает, как вытолкнуть приложения область действия сокета методом @Asynchronous EJB, который в свою очередь вызван каким-то фоновое задание (например, @Schedule).

В случае, если вы хотите вызвать нажатие на стороне EAR/EJB на приложение, использующее push-разъем, тогда вы можете использовать события CDI. Сначала создайте пользовательский класс bean-класса, представляющий событие push, например, PushEvent, используя все, что вы хотели бы передать как push-сообщение.

public final class PushEvent { 

    private final String message; 

    public PushEvent(String message) { 
     this.message = message; 
    } 

    public String getMessage() { 
     return message; 
    } 
} 

Затем используйте BeanManager.fireEvent(Object, java.lang.annotation.Annotation...) для запуска события CDI.

@Inject 
private BeanManager beanManager; 

public void onSomeEntityChange(Entity entity) { 
    beanManager.fireEvent(new PushEvent(entity.getSomeProperty())); 
} 

Наконец просто @Observes его в некотором запросе или приложение области действия КДИ управляемый компонент в WAR и делегат PushContext, как показано ниже.

@Inject @Push 
private PushContext someChannel; 

public void onPushEvent(@Observes PushEvent event) { 
    someChannel.send(event.getMessage()); 
} 

Ниже выдержка из documentation показывает, как толчок к сеансу или вид Scoped гнездо методом @Asynchronous EJB, который в свою очередь вызван некоторыми JSF действием.

В случае, если спусковой механизм на стороне EAR/EJB является асинхронным методом обслуживания, который, в свою очередь, инициирован на стороне WAR, тогда вы можете использовать обратные вызовы со стороны WAR.Пусть метод бизнес-службы принимает экземпляр обратного вызова в качестве аргумента, например. функциональный интерфейс java.util.function.Consumer.

@Asynchronous 
public void someAsyncServiceMethod(Entity entity, Consumer<Object> callback) { 
    // ... (some long process) 
    callback.accept(entity.getSomeProperty()); 
} 

И вызовите метод асинхронной службы в WAR, как показано ниже.

@Inject 
private SomeService someService; 

@Inject @Push 
private PushContext someChannel; 

public void someAction() { 
    someService.someAsyncServiceMethod(entity, message -> someChannel.send(message)); 
} 
Смежные вопросы