2010-04-20 3 views
2

Я уже задавал этот вопрос на форуме Icefaces, но тем временем я понял, что это более общая проблема.Server-initial Rendering: EJB -> FacesContext?

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

Проблема в том, как мне получить FacesContext из контейнера EJB?

В функции обработки сообщений FacesContext.getCurrentInstance() возвращает значение null.

Я также пытался сделать JSF-управляемый bean be be be MDB, но я не мог (кажется, вы не можете иметь оба в одном классе?).

Поскольку я новичок в мире JSF, я сейчас застрял. Есть ли способ заставить его работать?

(GlassFish v3 + Netbeans 6,8, JSF2 + ICEfaces 2,0 альфа2)

ответ

2

FacesContext - это HTTP-запрос и, следовательно, доступен только во время обработки HTTP-запроса, и даже тогда, когда URL-адрес запроса соответствует шаблону URL-адреса FacesServlet. Если вы не находитесь внутри потока, который выполняется сервером для обработки HTTP-запроса, то также нет средств для FacesContext. В контейнере EJB полностью отсутствуют средства HTTP-запросов.

Технически единственный способ сообщить EJB JSF о новом сообщении - позволить EJB запускать HTTP-запрос по URL-адресу, соответствующему шаблону url из FacesServlet, с сообщением в качестве параметра запроса. Вы можете использовать java.net.URLConnection. JSF, в свою очередь, может затем выполнить комету/HTTP-push-файл, чтобы обновить представление с помощью сообщения IceFaces, как вы упомянули.

E.g.

URL url = new URL("http://example.com/context/poll.jsf?msg=" + URLEncoder(msg, "UTF-8")); 
URLConenction connection = url.openConnection(); 
InputStream response = connection.getInputStream(); 

и poll.jsf, который прикреплен к опорной боба, как это:

@ManagedBean 
public class Poll { 

    @ManagedProperty(value="#{param.msg}") 
    private String msg; 

    @PostConstruct 
    public void init() { 
     // Do something with msg. 
    } 

    public void setMsg(String msg) { 
     this.msg = msg; 
    } 

} 

Примечание: с помощью JSF 2.0 аннотаций, но они должны быть самоуправления объяснения достаточно.

+1

Благодарим вас за ответ. Он работает, хотя и по-прежнему не является самым чистым решением (почему сервер приложений EE не имеет внутреннего способа делать это, не вызывая сервлет извне?), Но приемлемо. – egbokul

1

Я не эксперт, но я бы ожидать, что FacesContext доступен только во время обработки запроса JSF. Я боюсь, что вы не можете сделать именно то, что хотите, но вы, безусловно, сможете обойти это. На самом деле существует два вопроса:

  1. Как получить обновление через MDB на страницу JSF?
  2. Как обновить страницу на клиенте при возникновении события? Вы обычно не может передавать данные от сервера к клиенту, клиент должен requst их (хотя есть некоторые обходные пути, такие как http://en.wikipedia.org/wiki/Comet_(programming)))

я бы что-то вроде следующего:

  1. В MDB хранятся обновленные данные где-то - например, в глобальном кеше (сеансовый компонент без состояния с @Singleton и коллекция или карта для обновлений)
  2. Измените страницу JSF так, чтобы она запрашивала сервер для обновлений в регулярный интервал (желательно в backgrou й с помощью Ajax с помощью какой-то Ajax с поддержкой JSF CompoNet) - если есть обновление получено через MDB, сервер возвращает его, и страница будет вновь сделать себя
+0

Привет, спасибо за ответ. # 2 легко, потому что Icefaces 2.0 имеет свой класс PushRenderer, который хорошо работает. # 1 - вопрос: как я могу ссылаться на экземпляр класса, управляемый FacesServlet, если я вне его? EJB запускаются в другом контейнере ... – egbokul

+0

@egbokul # 1 вообще не обрабатывает wtl JSF, он просто хранит данные в сеансовом компоненте @Singleton, к которому JSF может получить доступ. Так что это JSF -> EJB, а не наоборот. Но с помощью PortableRenderer, о котором вы упоминаете, вы можете надеяться вытащить данные из MDB непосредственно в JSF. Мне любопытно, как это работает :-) Удачи! –

0

У меня есть обходной путь, который включает таймер на сторона JSF (к счастью, это только на сервере, не требуется связь AJAX и клиент-сервер), которая проверяет Singleton и при необходимости обновляет обновления. Однако я по-прежнему считаю, что это не правильное решение, и что это можно сделать без таймера ...

0

я также получил ответ на форуме ICEfaces:

org.icefaces.application.PortableRenderer обеспечивает объект, который может быть использован на не JSF потоков, чтобы вызвать толчок. (Это доступно в магистрали svn и будет предоставлено в следующем выпуске alpha (= Icefaces 2.0 alpha 3).)