【问题标题】:How to pass a managed bean as param at a facelet template如何在 facelet 模板中将托管 bean 作为参数传递
【发布时间】:2013-05-08 01:20:38
【问题描述】:

我在尝试将托管 bean 作为参数传递给 facelet 模板时遇到了很多麻烦。 我正在尝试在 facelet 模板上创建一个变量并通过 ui:param 传递其值,但我经常遇到“目标无法访问,标识符 'bean' 解析为空”错误。 我已经尝试将其设置为:

<p:commandButton value="Save" actionListener="#{sessionScope[bean].save}" />

它再次不起作用。

谁能帮帮我?

代码如下:

crud_template.xhtml

<ui:define name="content">

    <h:form>
        <ui:insert name="create_form">
            <!-- Default -->
        </ui:insert>

        <br />
        <br />
        <p:separator />
        <p:commandButton value="Save" actionListener="#{bean.save}" />
        <p:commandButton value="Cancel" actionListener="#{bean.cancel}" />
    </h:form>

</ui:define>

familyPersist.xhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:p="http://primefaces.org/ui">

<ui:composition template="/WEB-INF/templates/crud_template.xhtml">

    <ui:param name="bean" value="#{familyBean}" />

    <ui:define name="create_form">
        <h:panelGrid columns="3">
            <h:outputLabel value="Name*:" for="itemName" />
            <p:inputText id="itemName" required="true"
                value="#{familyBean.item.nmFamily}" />
        </h:panelGrid>
    </ui:define>

</ui:composition>
</html>

CrudBean.java

public abstract class CrudBean<T> {

    protected T item;

    private String redirect() {
        return "/pages/protected/" + getEntityName() + "List.jsf";
    }

    public String save() {
        return redirect();
    }

    public String cancel() {
        return redirect();
    }

    public abstract String getEntityName();

    /**
     * @return the item
     */
    public T getItem() {
        return item;
    }

    /**
     * @param item the item to set
     */
    public void setItem(T item) {
        this.item = item;
    }

}

FamilyBean.java

@Model
public class FamilyBean extends CrudBean<Family> {

    public FamilyBean() {
        item = new Family();
    }

    @Override
    public String getEntityName() {
        return "Family";
    }

}

最后,错误:

22:11:50,178 GRAVE [javax.faces.event] (http-localhost-127.0.0.1-8080-4) javax.el.PropertyNotFoundException: Target Unreachable, identifier 'bean' resolved to null
    at org.apache.el.parser.AstValue.getTarget(AstValue.java:98)
    at org.apache.el.parser.AstValue.invoke(AstValue.java:244)
    at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:278)
    at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:39)
    at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
    at javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:153)
    at javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)
    at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:769)
    at javax.faces.component.UICommand.broadcast(UICommand.java:300)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)
    at org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:62)
    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.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:489)
    at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50)
    at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155)
    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:368)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930)
    at java.lang.Thread.run(Thread.java:662)

编辑:

我使用这个 maven 命令创建我的项目:

mvn archetype:generate \
    -DarchetypeArtifactId=jboss-javaee6-webapp-archetype \
    -DarchetypeGroupId=org.jboss.spec.archetypes \
    -DarchetypeVersion=7.1.1.CR2

【问题讨论】:

    标签: java null facelets managed-bean param


    【解决方案1】:

    我尝试了上述所有建议,但没有运气。 唯一对我有用的是在调用方法时使用括号 '()'。我猜想属性未找到异常应该是它混淆了属性和方法的线索。我认为这是 facelets 的错误,因为它与传统的 JSF actionListener 和操作方法调用不一致。

    上面的例子应该适用于:

    &lt;p:commandButton value="Save" actionListener="#{bean.save()}" /&gt;

    在哪里

    &lt;ui:param name="bean" value="#{familyBean}" /&gt;

    【讨论】:

      【解决方案2】:

      我从文档中读到,@Model 等价于带有 RequestScoped 的@ManagedBean。

      因此,如果我尝试修复相同的问题,我可以执行以下操作:

      ui:param

      <ui:param name="bean" value="familyBean" />
      

      crud_template.xhtml 中:

      <p:commandButton value="Save" actionListener="#{requestscope[bean].save}" />
      

      试试这个,应该可以的。

      编辑:

      我确实尝试过复制相同的内容,并且能够解决。

      我在此处发布示例代码供您参考。

      还想分享一件事: 如果 bean 没有在 xhtml 中注入一次,您将无法从中获取引用。

      Template page:
      
      <ui:composition xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:a4j="http://richfaces.org/a4j">
      
      <h:head></h:head>
      
      <h:form>
          <ui:insert name="create_form">
              <!-- Default -->
          </ui:insert>
      
          <br />
          <br />
      
          <h:commandLink id="link" value="Name Converted">
              <f:ajax event="click" listener="#{requestScope[beantt].convertNameToUpperCase2}" execute="dateOfExpense" render="dateOfExpense" />
          </h:commandLink>
      
      </h:form>
      </ui:composition>
      

      示例测试页:

      <ui:composition xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:a4j="http://richfaces.org/a4j">
      
      <f:view>
          <h:body>
              <ui:composition template="testTemplate.xhtml">
      
                  <ui:param name="beantt" value="helloWorld" />
      
                  <ui:define name="create_form">
                      <h:panelGrid columns="3">
                          <h:outputLabel value="Name*:" for="itemName" />
                          <h:inputText size="20" value="#{helloWorld.name}" id="dateOfExpense"/>
                          <h:outputText value="#{requestScope}" />
                      </h:panelGrid>
      
                  </ui:define>
      
              </ui:composition>
      
          </h:body>
      </f:view>
      
      </ui:composition>
      

      后端 bean 类:(不使用原型)

       @Named("helloWorld")   //@Model was not available in my project
       public class HelloWorldBean {
      
          private String name;
      
          //Getters and Setters
      
          Logger LOG = LoggerFactory.getLogger(HelloWorldBean.class);
      
          public void convertNameToUpperCase2(AjaxBehaviorEvent event) {
               LOG.debug("Inside Bean");
               name = name.toUpperCase();
          }
       }
      

      更新的 Bean 类

       @javax.faces.bean.ManagedBean(name="helloWorld")
       @javax.enterprise.context.RequestScoped
       public class HelloWorldBean {
      
      private String name;
      
      // Getters and Setters
      
      // Logger LOG = LoggerFactory.getLogger(HelloWorldBean.class);
      
      public void convertNameToUpperCase2(AjaxBehaviorEvent event) {
          // LOG.debug("Inside Bean");
          name = name.toUpperCase();
      }
      
      public String getName() {
          return name;
      }
      
      public void setName(String name) {
          this.name = name;
      }
      }
      

      我还显示了请求范围内的所有可用变量,这将有助于找出正在查找的密钥是否实际可用。

      更新 这是我迄今为止的观察。如果您尝试连接@Named、@Model(它不适用于 UI,意味着无法在 xhtmls 中解析)。

      CDI 更像是将服务注入控制器或此处的 ManagedBean。

      例如演示 CDI 的示例:

      @Named("testCon")
      public class TestConsumer {
      
      public String convertNameToUpperCase2(String name) {
          // LOG.debug("Inside Bean");
          return  name.toUpperCase();
      }
      

      }

      @javax.faces.bean.ManagedBean(name="helloWorld") @javax.enterprise.context.RequestScoped 公共类 HelloWorldBean {

      @Inject
      @Named("testCon")
      private TestConsumer test;
      
      private String name;
      
      // Getters and Setters
      
      // Logger LOG = LoggerFactory.getLogger(HelloWorldBean.class);
      
      public void convertNameToUpperCase2(AjaxBehaviorEvent event) {
          name = test.convertNameToUpperCase2(name);
      }
      
      public String getName() {
          return name;
      }
      
      public void setName(String name) {
          this.name = name;
      }
       }
      

      【讨论】:

      • 这给我留下了以下错误:actionListener="#{requestScope[bean].save}": Target Unreachable, 'familyBean' returned null
      • 我试图执行你传递给我的确切代码,但它再次给了我同样的错误:/WEB-INF/templates/testTemplate.xhtml @26,54 listener="#{requestScope[beantt].convertNameToUpperCase2}": Target Unreachable, 'helloWorld' returned null: javax.el.PropertyNotFoundException: /WEB-INF/templates/testTemplate.xhtml @26,54 listener="#{requestScope[beantt].convertNameToUpperCase2}": Target Unreachable, 'helloWorld' returned null,代码怎么能在那里运行得很好,而这里却没有......也许是 pom .xml 正在导入一些与您不同的依赖项?
      • 我更新了问题并把我用来创建项目的 mvn 命令... maven archetype...
      • 您是否创建了 name 的 getter 和 setter,并且我已经打印了 requestscope 中所有可用的变量,您看到那里的 helloWorld 键了吗?
      • 好的,我会在某个时候检查原型,但我非常怀疑这是否会成为问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-09
      • 2013-12-11
      • 1970-01-01
      • 2011-09-14
      • 1970-01-01
      • 2021-04-29
      • 2012-03-03
      相关资源
      最近更新 更多