Получение параметра GET-запроса в bean-компонент @ViewScoped - PullRequest
3 голосов
/ 11 октября 2011

У меня есть (в области запроса) список, из которого пользователь может выбрать «PQ» (список ссылок). При нажатии или вводе в браузере иным способом должна отображаться главная страница для каждого PQ. Страница каждого PQ имеет вид

http://localhost:8080/projectname/main.jsf?id=2

Вот сначала боб PQ:

@Named
@ViewScoped
public class PqHome implements Serializable
{
    @PersistenceContext(unitName="...")
    private EntityManager em;

    private Integer id;
    private PQ instance;

    @PostConstruct
    public void init()
    {
        System.out.println("ID is " + id); // ID from URL param

        instance = em.find(PQ.class, id);       
    }

    public Integer getId()
    {
        return id;
    }

    public void setId(Integer id)
    {
        this.id = id;
    }

    public PQ getInstance()
    {
        return instance;
    }
}

Вот main.xhtml:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                ...>
  <ui:define name="metadata">
    <f:metadata>
      <f:viewParam name="id" value="#{pqHome.id}">
        <f:convertNumber integerOnly="#{true}" />
      </f:viewParam>
      <!--f:event type="preRenderView" listener="#{pqHome.init}" /-->
    </f:metadata>
  </ui:define>
  <ui:define name="title">
    <h:outputText value="Main" />
  </ui:define>
  ...
</ui:composition>

Каждый раз, когда я выбираю или иным образом обновляю страницу / URL, я получаю NullPointerException от EntityManager:

org.jboss.weld.exceptions.WeldException: WELD-000049 Unable to invoke [method] @PostConstruct public de.mycomp.myproj.beans.PqHome.init() on de.mycomp.myproj.beans.PqHome@4f0ea68f
    at org.jboss.weld.bean.AbstractClassBean.defaultPostConstruct(AbstractClassBean.java:595)
...
Caused by: java.lang.IllegalArgumentException: id to load is required for loading
at org.hibernate.event.spi.LoadEvent.<init>(LoadEvent.java:87)
at org.hibernate.event.spi.LoadEvent.<init>(LoadEvent.java:59)
at org.hibernate.internal.SessionImpl.get(SessionImpl.java:961)
at org.hibernate.internal.SessionImpl.get(SessionImpl.java:957)
at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:787)
at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:762)
at org.jboss.as.jpa.container.AbstractEntityManager.find(AbstractEntityManager.java:221)
at de.mycomp.myproj.beans.PqHome.init(PqHome.java:47)
... 56 more

[Строка 47 - em.find (...)]

Линия

<f:event type="preRenderView" listener="#{pqHome.init}" />

не делает вещи лучше. Теперь я в полном отчаянии.

Как получить URL запроса GET в bean-компоненте @ViewScoped?

Примечание : Держу пари, это не тривиальная вещь. Скорее всего, я делаю что-то не так концептуально, поэтому любые советы о том, как улучшить, приветствуются. Я чувствовал, что мне нужно выбрать @ViewScoped, потому что на этой странице будет более сложный графический интерфейс на основе AJAX, который я действительно хотел бы сделать доступным через параметры URL GET.

Спасибо

Ответы [ 2 ]

6 голосов
/ 23 марта 2012

Есть лучший способ получить идентификатор из URL.Просто используйте его в методе @PostConstruct init (), чтобы получить «id» из URL:

FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("id");

Вы все еще можете использовать ViewScoped и @ PostConstruct.

6 голосов
/ 11 октября 2011

@PostConstruct вызывается напрямую после построения бина и внедрения всех зависимостей (таких как @PersistenceContext, @EJB, @ManagedProperty, @Inject и т. Д. И т. Д.).

<f:viewParam> устанавливает свое значение во время фазы обновления значений модели, которая наступает намного позже (после) построения компонента.Так что внутри @PostConstruct значение <f:viewParam> просто еще не установлено.В этот момент все равно будет null.

Вы близки с <f:event type="preRenderView">, но вам нужно удалить аннотацию @PostConstruct.

Итак:

<f:viewParam name="pq" value="#{pqHome.id}">
    <f:convertNumber integerOnly="#{true}" />
</f:viewParam>
<f:event type="preRenderView" listener="#{pqHome.init}" />

с

private Integer id;

public void init() {
    instance = em.find(PQ.class, id);       
}

Не связанным с конкретной проблемой, я бы предложил вместо этого использовать Converter.См. Также Связь в JSF 2.0 - Преобразование и проверка параметров запроса GET .

Также комбинация @Named @ViewScoped не будет работать так, как задумано.Специфичный для JSF @ViewScoped работает в сочетании только со специфическим для JSF @ManagedBean.Ваш CDI-специфичный @Named будет вести себя как @RequestScoped таким образом.Либо используйте @ManagedBean вместо @Named, либо используйте CDI-специфичные @ConversationScoped вместо @ViewScoped.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...