JSF 2:bean 的属性假定为写入而不是读取?

发布于 2024-12-09 14:02:56 字数 6365 浏览 0 评论 0原文

我有以下简单视图 main.xhtml,请求 URL 类似于:

http://localhost:8080/myproj/main.jsf?pq=2

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                xmlns:c="http://java.sun.com/jsp/jstl/core"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:ui="http://java.sun.com/jsf/facelets"
                xmlns:a4j="http://richfaces.org/a4j"
                xmlns:rich="http://richfaces.org/rich"
                template="/templating/layout-2col.xhtml">

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

  ...

  <ui:define name="content-right">
    <h:form>
      <rich:panel>
        <f:facet name="header">
          Menu
        </f:facet>
        <rich:tabPanel binding="#{pqHome.tabPanel}">        
        </rich:tabPanel>
      </rich:panel>
    </h:form>
  </ui:define>

</ui:composition>

My bean:

@ManagedBean
@RequestScoped
public class PqHome implements Serializable
{
    @Inject
    private PqService pqService;

    //@ManagedProperty(value="#{param.pq}")
    private Integer id;
    private Prequalification instance;

    @Inject
    private PqPartnerListQuery pplq;
    private List<Partner> partners;

    private UITabPanel tabPanel;
    private List<UIComponent> tabs;

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

        instance = pqService.findSingleInstance(id);

        partners = pplq.getItemsForPq(id);

        System.out.println("Building tab manually...");

        // RF way...
        FacesContext fc = FacesContext.getCurrentInstance();
        Application application = FacesContext.getCurrentInstance().getApplication();

        tabPanel = (UITabPanel)application.createComponent(UITabPanel.COMPONENT_TYPE);
        tabPanel.setSwitchType(SwitchType.client);

        tabs = tabPanel.getChildren();

        for ( Partner partner : partners )
        {
            Company co = partner.getCompany();
            String companyName = co.getName();

            UITab tab = (UITab)application.createComponent(UITab.COMPONENT_TYPE);

            //tab.setTitle(companyName);
            tab.setName(companyName);
            tab.setId(co.getDndType());

            tabs.add(tab);
        }

        String firstTabName = partners.get(0).getCompany().getName();

        System.out.println("First tab name = " + firstTabName);

        tabPanel.setActiveItem(firstTabName);
    }

    public Integer getId()
    {
        return id;
    }

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

    public Prequalification getInstance()
    {
        return instance;
    }

    public UITabPanel getTabPanel()
    {
        return tabPanel;
    }
}

当请求上述页面时,我收到一条错误消息:

An Error Occurred:
/main.xhtml @221,53 binding="#{pqHome.tabPanel}": The class 'de.mycomp.myproj.beans.PqHome' does not have a writable property 'tabPanel'.
+- Stack Trace

javax.el.PropertyNotWritableException: /main.xhtml @221,53 binding="#{pqHome.tabPanel}": The class 'de.mycomp.myproj.beans.PqHome' does not have a writable property 'tabPanel'.
    at com.sun.faces.facelets.el.TagValueExpression.setValue(TagValueExpression.java:136)
    at com.sun.faces.application.ApplicationImpl.createComponentApplyAnnotations(ApplicationImpl.java:1897)
    at com.sun.faces.application.ApplicationImpl.createComponent(ApplicationImpl.java:1109)
    at org.jboss.as.weld.webtier.jsf.ForwardingApplication.createComponent(ForwardingApplication.java:122)
    at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.createComponent(ComponentTagHandlerDelegateImpl.java:511)
    at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:157)
    at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120)
    at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:98)
    at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:137)
    at org.richfaces.view.facelets.html.BehaviorsAddingComponentHandlerWrapper.applyNextHandler(BehaviorsAddingComponentHandlerWrapper.java:55)
...
    at org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:67)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)
    at org.jboss.as.web.NamingValve.invoke(NamingValve.java:57)
    at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:49)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:154)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:362)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:667)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:951)
    at java.lang.Thread.run(Unknown Source)

为什么 JSF 假定选项卡面板 EL binding="#{pqHome.tabPanel}" 可以在此处写入/可写?有没有办法解决这个问题,那就是告诉 JSF 阅读这里?

注意:解决方法是取消注释 bean 中的 @ManagedProperty@PostConstruct 注释,并取消注释 在视图中,但我不明白为什么我应该使用 ...

谢谢

I have the following simple view main.xhtml, the request URL would be something like:

http://localhost:8080/myproj/main.jsf?pq=2

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                xmlns:c="http://java.sun.com/jsp/jstl/core"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:ui="http://java.sun.com/jsf/facelets"
                xmlns:a4j="http://richfaces.org/a4j"
                xmlns:rich="http://richfaces.org/rich"
                template="/templating/layout-2col.xhtml">

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

  ...

  <ui:define name="content-right">
    <h:form>
      <rich:panel>
        <f:facet name="header">
          Menu
        </f:facet>
        <rich:tabPanel binding="#{pqHome.tabPanel}">        
        </rich:tabPanel>
      </rich:panel>
    </h:form>
  </ui:define>

</ui:composition>

My bean:

@ManagedBean
@RequestScoped
public class PqHome implements Serializable
{
    @Inject
    private PqService pqService;

    //@ManagedProperty(value="#{param.pq}")
    private Integer id;
    private Prequalification instance;

    @Inject
    private PqPartnerListQuery pplq;
    private List<Partner> partners;

    private UITabPanel tabPanel;
    private List<UIComponent> tabs;

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

        instance = pqService.findSingleInstance(id);

        partners = pplq.getItemsForPq(id);

        System.out.println("Building tab manually...");

        // RF way...
        FacesContext fc = FacesContext.getCurrentInstance();
        Application application = FacesContext.getCurrentInstance().getApplication();

        tabPanel = (UITabPanel)application.createComponent(UITabPanel.COMPONENT_TYPE);
        tabPanel.setSwitchType(SwitchType.client);

        tabs = tabPanel.getChildren();

        for ( Partner partner : partners )
        {
            Company co = partner.getCompany();
            String companyName = co.getName();

            UITab tab = (UITab)application.createComponent(UITab.COMPONENT_TYPE);

            //tab.setTitle(companyName);
            tab.setName(companyName);
            tab.setId(co.getDndType());

            tabs.add(tab);
        }

        String firstTabName = partners.get(0).getCompany().getName();

        System.out.println("First tab name = " + firstTabName);

        tabPanel.setActiveItem(firstTabName);
    }

    public Integer getId()
    {
        return id;
    }

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

    public Prequalification getInstance()
    {
        return instance;
    }

    public UITabPanel getTabPanel()
    {
        return tabPanel;
    }
}

When requesting the above page I get an error saying:

An Error Occurred:
/main.xhtml @221,53 binding="#{pqHome.tabPanel}": The class 'de.mycomp.myproj.beans.PqHome' does not have a writable property 'tabPanel'.
+- Stack Trace

javax.el.PropertyNotWritableException: /main.xhtml @221,53 binding="#{pqHome.tabPanel}": The class 'de.mycomp.myproj.beans.PqHome' does not have a writable property 'tabPanel'.
    at com.sun.faces.facelets.el.TagValueExpression.setValue(TagValueExpression.java:136)
    at com.sun.faces.application.ApplicationImpl.createComponentApplyAnnotations(ApplicationImpl.java:1897)
    at com.sun.faces.application.ApplicationImpl.createComponent(ApplicationImpl.java:1109)
    at org.jboss.as.weld.webtier.jsf.ForwardingApplication.createComponent(ForwardingApplication.java:122)
    at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.createComponent(ComponentTagHandlerDelegateImpl.java:511)
    at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:157)
    at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120)
    at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:98)
    at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:137)
    at org.richfaces.view.facelets.html.BehaviorsAddingComponentHandlerWrapper.applyNextHandler(BehaviorsAddingComponentHandlerWrapper.java:55)
...
    at org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:67)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)
    at org.jboss.as.web.NamingValve.invoke(NamingValve.java:57)
    at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:49)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:154)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:362)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:667)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:951)
    at java.lang.Thread.run(Unknown Source)

Why does JSF assume the tab panel EL binding="#{pqHome.tabPanel}" to be written/writable here? Is there a way to fix this, that is tell JSF to read here?

Note: The workaround would be to uncomment the @ManagedProperty and @PostConstruct annotations in the bean and outcomment the <f:event ...> in the view, but then I don't see why I should be using <f:viewParam> and <f:metadata> at all...

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

故事还在继续 2024-12-16 14:02:56

JSF 只需要在支持 bean 中设置获取的或自动创建的非 null 组件,就像您通过绑定 告诉它的那样。您需要提供一个 setter 方法。没有任何借口。如果 getter 返回手动创建的组件,则将设置完全相同的组件。 JSF 不会设置自动创建的。

JSF just needs to set the obtained or auto-created non-null component in the backing bean as you told it to do by binding. You need to provide a setter method. No excuses. If the getter returned a manually created component, just the very same component will be set. JSF won't set the auto-created one.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文