3

我有一个(请求范围的)列表,用户可以从中选择“PQ”(链接列表)。当单击或以其他方式进入浏览器时,应显示每个 PQ 的主页。每个 PQ 的页面的格式为

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

首先是 PQ bean:

@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 时,我都会NullPointerExceptionEntityManager

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 请求参数放入@ViewScopedbean?

注意:我敢打赌这不是一件小事。很有可能我在概念上做错了什么,所以欢迎任何关于如何改进的提示。我觉得我需要选择@ViewScoped,因为该页面上会有更复杂的基于 AJAX 的 GUI,我真的很想通过 URL GET 参数保持访问。

谢谢

4

2 回答 2

7

有一种更好的方法可以从 url 获取 id。只需在 @PostConstruct init() 方法中使用它来从 url 获取“id”:

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

您仍然可以使用 ViewScoped 和 @PostConstruct。

于 2012-03-23T15:34:15.313 回答
6

在 bean的构造和所有依赖注入(例如, , , , etc..etc..)之后直接@PostConstruct调用。@PersistenceContext@EJB@ManagedProperty@Inject

<f:viewParam>更新模型值阶段设置它的值,该阶段在 bean 的(后)构造之后很长时间。所以里面的@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);       
}

与具体问题无关,我建议改用 a Converter。另请参阅JSF 2.0 中的通信-转换和验证 GET 请求参数

此外,该组合@Named @ViewScoped不会按预期工作。JSF @ViewScoped-specific 仅与 JSF-specific 结合使用@ManagedBean。您的 CDI 特定的@Named行为将像@RequestScoped这种方式。使用@ManagedBean代替@Named或使用特定于 CDI 的@ConversationScoped而不是@ViewScoped.

于 2011-10-11T12:41:44.703 回答