Подтвердить что ты не робот

JSF Управляемый Bean автосоздание?

Можно ли автоматически создать управляемый JSF bean?

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

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

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

4b9b3361

Ответ 1

Используйте Application#evaluateExpressionGet(). Он будет создавать 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 или старше, используя устаревший Application#createValueBinding():

FacesContext context = FacesContext.getCurrentInstance();
Bean bean = (Bean) context.getApplication().createValueBinding("#{bean}").getValue(context);

Ответ 2

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

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.

Ответ 3

Один из механизмов заключается в том, чтобы вставить 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>

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

Ответ 4

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

FacesContext context = FacesContext.getCurrentInstance();

Bean Bean= (Bean) context.getApplication(). evaluateExpressionGet (контекст, "# { bean}", Bean.class);

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