Автоматическое создание управляемого компонента JSF?

Возможно ли автоматическое создание управляемого bean-компонента JSF?

Например, у меня есть несколько bean-компонентов с ограниченным сеансом. Иногда возникает необходимость получить доступ к этим экземплярам в коде (а не только в JSF), это делается с помощью:

PageBean pageBean = (PageBean) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("pages");

Однако, если ни одна страница еще не была посещена, которая вызывает '# {pages}', это преобразуется в null ... есть ли способ заставить JSF создать bean-компонент, когда область 'начинается'? Итак, в этом случае в идеале, когда пользовательский сеанс начинается, bean-компонент 'pages' должен быть немедленно создан в сеансе?


person rat    schedule 12.01.2010    source источник


Ответы (4)


Используйте _ 1_. Он создаст bean-компонент, когда это еще не сделано.

FacesContext context = FacesContext.getCurrentInstance();
Bean bean = (Bean) context.getApplication().evaluateExpressionGet(context, "#{bean}", Bean.class);

Где "bean" - имя управляемого bean-компонента, а Bean.class - соответствующий вспомогательный класс bean-компонента.

При необходимости вы можете обернуть это вспомогательным методом, чтобы не было необходимости в приведении типов (ребята из JSF не воспользовались универсальными шаблонами и параметром Class в evaluateExpressionGet):

public static <T> T findBean(String managedBeanName, Class<T> beanClass) {
    FacesContext context = FacesContext.getCurrentInstance();
    return beanClass.cast(context.getApplication().evaluateExpressionGet(context, "#{" + managedBeanName + "}", beanClass));
}

который можно использовать как:

Bean bean = findBean("bean", Bean.class);

Или без типа, но с @SuppressWarnings:

@SuppressWarnings("unchecked")
public static <T> T findBean(String managedBeanName) {
    FacesContext context = FacesContext.getCurrentInstance();
    return (T) context.getApplication().evaluateExpressionGet(context, "#{" + managedBeanName + "}", Object.class);
}

который можно использовать как:

Bean bean = findBean("bean");

Обновление: указанное выше относится к JSF 1.2. Вот способ для JSF 1.1 или более ранней версии с использованием устаревшего _ 12_:

FacesContext context = FacesContext.getCurrentInstance();
Bean bean = (Bean) context.getApplication().createValueBinding("#{bean}").getValue(context);
person BalusC    schedule 12.01.2010
comment
Спасибо за это, моя IDE хромает с загрузкой классов на этом, но я считаю, что это правильный способ сделать это ... глупое затмение WAS и его встроенные библиотеки. - person rat; 12.01.2010
comment
БЫЛ? Кстати, мой ответ ориентирован на JSF 1.2 (которому уже почти 4 года). WAS использовался для поставки с устаревшим JSF 1.1 в течение очень долгого времени, вплоть до версии 6.1 примерно в 2007 году. Я отредактирую свой ответ и скоро добавлю JSF 1.1. - person BalusC; 12.01.2010
comment
WAS = сервер приложений websphere В любом случае, я решил, что это должно быть 1.2, так как WAS включает 1.1 библиотеки, и он не показывал метод как действительный, я изменил загрузку класса, хотя и теперь он работает нормально, еще раз спасибо: D - person rat; 12.01.2010
comment
Да, я знаю, что означает WAS :) Я даже упомянул, что раньше он поставлялся с JSF 1.1 по умолчанию. Рад, что у тебя получилось работать. Не забудьте отметить ответ как принятый. - person BalusC; 12.01.2010
comment
Не прочитал ваш комментарий полностью перед публикацией, в любом случае я вошел в систему и дам вам + спасибо: D - person rat; 12.01.2010
comment
Привет, BalusC: разве простая инъекция bean-компонентов с @ManagedProperty не решит проблему OP? - person Thang Pham; 09.05.2012
comment
@Thang: упомянутый OP Иногда возникает необходимость получить доступ к этим экземплярам в коде (а не только в JSF), поэтому я понял, что внедрение его как управляемого свойства по какой-то причине не подходит. Также обратите внимание на комментарий OP к ответу Макдауэлла, причина, похоже, в ленивой загрузке. - person BalusC; 09.05.2012
comment
@BalusC Правильный ли здесь ответ? В конце концов, инициатор потока запросил отсутствующие компоненты сеанса, в то время как «context.getApplication (). CreateValueBinding» создается для создания bean-компонентов в приложении области видимости, не так ли? - person wh81752; 02.12.2014
comment
Он работает нормально, но я хочу знать ¿в чем разница между этим методом и использованием @ManagedProperty (bean)? - person Pedro García Medina; 31.03.2015
comment
@Pedro: Один - JSF 1.x, другой - JSF 2.x. Внимательно обратите внимание на даты и версии. - person BalusC; 31.03.2015

Что насчет этого решения:

public static Object getBean(String beanName)
{          
    Object returnObject = FacesContext.getCurrentInstance().getELContext().getELResolver().getValue(FacesContext.getCurrentInstance().getELContext(), null, beanName);  
    if (returnObject == null)  
        System.out.println("Bean with name " + beanName + " was not found. Check the faces-config.xml file if the given bean name is ok.");          
    return returnObject;
}

Таким образом вы даже можете избежать использования параметра Bean.class.

person Vic    schedule 07.05.2011
comment
Это хорошая техника, мне она больше нравится. Об этом также упоминается в блоге Олега ovaraksin.blogspot .com / 2011/11 / +1 - person Thang Pham; 05.03.2012

Один из механизмов - внедрить bean-компонент в bean-компонент, на который вы хотите ссылаться, в другой bean-компонент, как показано здесь с помощью expensiveBean:

  <managed-bean>
    <managed-bean-name>requestBean</managed-bean-name>
    <managed-bean-class>lifetime.RequestBean</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
    <managed-property>
      <property-name>cachedAsset</property-name>
      <property-class>lifetime.ExpensiveBean</property-class>
      <value>#{expensiveBean}</value>
    </managed-property>
  </managed-bean>

Это не очень "лениво", но может быть удобно.

person McDowell    schedule 12.01.2010
comment
Я уже использую инъекцию, в этом случае нужно быть более ленивым, но спасибо :) - person rat; 12.01.2010

Вопрос: будет ли использовать

FacesContext context = FacesContext.getCurrentInstance ();

Бин bean = (Bean) context.getApplication (). AssessmentExpressionGet (context, # {bean}, Bean.class);

вызывать создание экземпляра нового Бина каждый раз, когда код запускается через эти операторы? Или он просто будет относиться к тому же самому экземпляру, созданному изначально?

person Sean    schedule 06.12.2010