【问题标题】:JSF2 composite component throws PropertyNotFoundException for action methodJSF2 复合组件为 action 方法抛出 PropertyNotFoundException
【发布时间】:2010-08-15 13:10:53
【问题描述】:

我有一个复合组件:

<composite:interface>
    <composite:attribute name="actionMethod" 
        method-signature="java.lang.String action()" required="true" />
</composite:interface>

<composite:implementation>
    <h:form>
        <h:commandButton id="captureButton" value="#{msgs.capture}" 
            action="#{cc.attrs.actionMethod}" />
    </h:form>
</composite:implementation>

以及调用该复合组件的页面:

<ezcomp:captureTitle actionMethod="#{saveDecisionsBean.captureTitle}" />

还有一个包含动作的bean:

@Named(value="saveDecisionsBean")
@SessionScoped
public class SaveDecisionsBean extends BackingBeanBase {
    ...
    public String captureTitle() {
        ...
    }
}

现在这是我的问题。当我尝试运行它时,它说 SaveDecisionsBean 没有属性 captureTitle。因此,我必须添加一个SaveDecisionsBean#getCaptureTitle() 方法。当我这样做时,它运行得很好。为什么我必须定义这个方法?它在&lt;composite:attribute /&gt; 中说它是一个方法,它被用作一个动作。

这是我得到的确切错误消息:

javax.el.PropertyNotFoundException: /index.xhtml @54,86 
    actionMethod="#{saveDecisionsBean.captureTitle}": 
    The class 'com.example.persistence.SaveDecisionsBean_$$_javassist_209'
    does not have the property 'captureTitle'.

(出于 SEO 原因:其他实现可能会显示类名 WeldClientProxy。)

【问题讨论】:

  • 作为注释,如果类名相同,则不必写@Named(value="saveDecisionsBean")
  • 它在 NetBeans 中默认这样做。
  • 顺便说一句,如果上述方法可行,那么也可以使用&lt;composite:attribute name="actionMethod" targets="captureButton" required="true" /&gt;,因此无需method-signature。但同样的问题。
  • 仅供参考。基础错误已修复。 java.net/jira/browse/JAVASERVERFACES-1806

标签: jsf jsf-2 composite-component


【解决方案1】:

我遇到了同样的问题,我发现这是由于我的操作方法确实抛出了 IllegalArgumentException。同时,这已被报告为一个错误: Composite action method throws PropertyNotFoundException when method throws any exception

棘手的部分(至少对我而言)是我的应用程序一直运行良好,直到我将部分代码移动到复合组件 (CC) 中。在我的应用程序捕获 IAE 并显示一个很好的错误消息之前,但是在使用 CC 时,JSF 验证(或其他任何东西......)首先捕获这个并产生这个相当混乱的错误消息。

我使用 BalusC 提供的测试代码的修改版本验证了这一点(见下文)。测试页面显示了两个输入和提交按钮组件。如果您在文本字段中输入某些内容(“恐慌”(不带引号)除外),CC 版本和“内联”版本都有效(观看标准输出)。如果您在“内联”版本中输入“panic”,您会按预期注意到 IAE,但如果您在上面的“CC 版本”中输入相同的内容,您将看到 PropertyNotFoundException。似乎 JSF 被 IAE 弄糊涂了,并决定该属性必须是一个属性,而不是一个操作方法……不知道这是一个错误还是一个特性。这是根据规范,有人知道吗?

因此,这里的结论是,您不能在 CC 中将操作方法​​与引发异常的 bean 一起使用。对我来说,这意味着我不能使用复合组件。伤心!

希望这会有所帮助...

/resources/components/test.xhtml

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:cc="http://java.sun.com/jsf/composite">
<cc:interface>
  <cc:attribute name="text"/>
  <cc:attribute name="action" method-signature="java.lang.String action()" required="true" />
</cc:interface>
<cc:implementation>
  <h:form>
    <h:inputText value="#{cc.attrs.text}"/>
    <h:commandButton value="submit" action="#{cc.attrs.action}" />
  </h:form>
</cc:implementation>

/test.xhtml

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:cc="http://java.sun.com/jsf/composite/components">
<h:head>
  <title>Test</title>
</h:head>
<h:body>
  <!-- text and cmd-button as cc -->
  <cc:test text="#{bean.text}" action="#{bean.submit}" />

  <hr/>

  <!-- text and cmd-buuton inline -->
  <h:form id="inline">
    <h:inputText value="#{bean.text}"/>
    <h:commandButton value="submit2" action="#{bean.submit}" />
  </h:form>
</h:body>
</html>

最后是豆子:

@ManagedBean
@RequestScoped
public class Bean {

  private String text;

  public String getText() {
    return text;
  }

  public void setText(String text) {
    this.text = text;
  }

  public String submit() {
        if (text.equalsIgnoreCase("panic")){
          throw new IllegalArgumentException("Panic!");
        }

        System.out.println(text);

        return null;
    }
}

【讨论】:

  • 当然,您可以添加 Faces Message 而不是抛出 IAE:
  • FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Some error...."); 但这打破了 bean(作为简单 POJO)和 JSF/Faces 的分离
  • 你完全正确!这绝对是一个错误。我会向 JSF 男孩报告这件事。
  • 请注意,如果您删除异常并且您的方法抛出任何 RuntimeException JSF 将抛出 PropertyNotFoundException 异常
  • 这是一个基本的用例,你会认为会有一个单元测试。差不多两年后,我仍然无法创建一个带有验证器的复合组件。
【解决方案2】:

奇怪,我无法使用 Mojarra 2.0.2 重现此问题。也许代码中有更多的东西与一个或另一个发生冲突?或者您没有运行您认为正在运行的代码?

为了完整起见,我将包含我用来尝试重现此问题的测试 sn-ps:

/resources/components/test.xhtml

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:cc="http://java.sun.com/jsf/composite">
    <cc:interface>
        <cc:attribute name="action" method-signature="java.lang.String action()" required="true" />
    </cc:interface>
    <cc:implementation>
        <h:form>
            <h:commandButton value="submit" action="#{cc.attrs.action}" />
        </h:form> 
    </cc:implementation>
</html>

/test.xhtml

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:h="http://java.sun.com/jsf/html" 
    xmlns:cc="http://java.sun.com/jsf/composite/components">
    <h:head>
        <title>Test</title>
    </h:head>
    <h:body>
        <cc:test action="#{bean.submit}" />
    </h:body>
</html>

com.example.Bean

package com.example;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean
@RequestScoped
public class Bean {

    public String submit() {
        System.out.println("submit");
        return null;
    }

}

以上方法也适合你吗?

【讨论】:

  • 这对我来说很好,即使使用 CDI。我将不得不进一步调查。
  • 可能是嵌套形式?另请参阅 this answer 以获取其他提示。
  • 绝对没有嵌套形式...我确实在 bean 中使用 CDI(我从两个不同的范围注入 3 个不同的 bean。此外,我使用所需的视图参数。我不确定这是否会有所不同。我不认为它会因为实例化或视图参数的问题会在实际尝试调用操作之前抛出异常。
猜你喜欢
  • 2016-07-27
  • 1970-01-01
  • 1970-01-01
  • 2011-11-27
  • 2011-11-10
  • 2012-12-07
  • 2012-04-10
  • 2012-09-10
  • 1970-01-01
相关资源
最近更新 更多