无法通过EL传递参数到方法 - javax.el.MethodNotFoundException

时间:2012-01-09 20:49:16

标签: java jsf tomcat primefaces el

使用JSF 2.0和EL,我试图在POJO上调用一个方法,POJO是一个viewscoped bean的属性。该代码实际上非常类似于 @BalusC 的教程here。当我调用一个不带参数的方法时,一切都很好。但是当我尝试调用一个带参数的方法时,我得到以下异常:

javax.faces.el.MethodNotFoundException: javax.el.MethodNotFoundException:
/user.xhtml at line 42 and column 32 action="#{users.user.removeFriend(friend)}":
Method not found: model.User@67f2b0dd.removeFriend()

以下是一些更多细节:

user.xhtml

<f:metadata>
    <f:viewParam name="id" value="#{users.id}" />
    <f:event type="preRenderView" listener="#{users.init}" />
</f:metadata>

...

<h:form id="usersForm">
    <p:outputPanel>    
        <p:dataTable id="userTable" value="#{users.user.friendList}" var="friend">
            <p:column>
                <h:outputText value="#{friend.name}" />
            </p:column>
            <p:column>
                <p:commandButton action="#{users.user.removeFriend(friend)}"
                    ajax="true"
                    update="userTable somethingElse" process="@this"
                    onerror="errorDialog.show();"
                    icon="ui-icon-delete"
                    title="delete user">
                </p:commandButton>
            </p:column>
        </p:dataTable>
    </p:outputPanel>

    <p:commandButton action="#{users.user.removeAllFriends()}" ajax="true"
                update="userTable somethingElse"
                process="@this"
                icon="ui-icon-close"
                value="delete all friends?">
    </p:commandButton>


</h:form>

我有以下ViewScoped bean:

Users.java

@ManagedBean(name = "users")
@ViewScoped
public class Users implements Serializable {
    private static final long serialVersionUID = 1L;

    private String id;
    private User user;

    @ManagedProperty("#{userService}")
    private UserService userService; // session scoped

    public void init() {
        user = userService.getCart(id);
    }

    public final String getId() {
        return id;
    }

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

    public final User getUser() {
        return user;
    }

    public final void setUser(User user) {
        this.user= user;
    }

    public final void setUserService(UserService userService) {
        this.userService = userService;
    }

}

User类 - 一个POJO - 具有private List<Friend> friends属性,包含getter和setter以及public方法User#removeFriend(Friend f)。它有另一个public方法; User#removeAllFriends()

页面呈现正常,但当我点击表格中用户旁边的“删除”commandButton时,我得到了异常。

这里有什么问题?为什么我可以成功调用无参数方法但不能将参数传递给另一个?

编辑:如果有任何好处,应用程序将部署在Tomcat 7.0上。

任何帮助表示感谢。

更新:正如BalusC和Neo指出的那样,这是Tomcat 7.0的一个问题。我安装了WebLogic 12.1,一切正常。

4 个答案:

答案 0 :(得分:7)

这是Tomcat中的一个错误。它直接在bean上调用方法时有效,但在嵌套属性上调用它时则无效。我记得这个问题是issue 50449我曾经报道但是因为“为我工作”而被关闭(也许他们没有对它进行非常正确的测试,我觉得再次与Tomcat的人争论是不值得的,我没有很好的经验)。无论如何,我已经用issue 52445重新报告了一个更加可靠的测试用例 - 我希望。

同时,用Glassfish代替不同的EL实现应该可以解决。但我可以告诉你,无论你想做什么,都不是真正适当的方法。您已在模型(User实体类)上声明了一个业务方法,而不是在控制器(Users托管bean类)上。这个不对。该模型应仅用于保存数据。控制器应该用于保存业务操作。

我建议按如下方式重写您的案例:

<h:form id="usersForm">
    <p:outputPanel>    
        <p:dataTable id="userTable" value="#{users.user.friends}" var="friend">
            <p:column>
                <h:outputText value="#{friend.name}" />
            </p:column>
            <p:column>
                <p:commandButton action="#{users.removeFriend(friend)}"
                    process="@this" update="userTable somethingElse" onerror="errorDialog.show();"
                    icon="ui-icon-delete" title="delete user" />
            </p:column>
        </p:dataTable>
    </p:outputPanel>

    <p:commandButton action="#{users.removeAllFriends}"
        process="@this" update="userTable numUsers"
        value="delete all friends?" />
</h:form>

并将业务方法放在Users托管bean中:

public void removeFriend(Friend friend) {
    userService.removeFriend(user, friend);
    // ...
}

public void removeAllFriends() {
    userService.removeAllFriends(user);
    // ...
}

UserService另一个@ManagedBean也不完全正确。它应该是一个@Stateless EJB,但这是另一个故事。 Tomcat不支持EJB,而不用例如OpenEJB来丰富它。没有EJB,它不一定需要是另一个托管bean。您不希望直接将这些服务公开到视图中。

答案 1 :(得分:1)

啊......这解释了它@ Tomcat ..你传递参数“#{users.user.removeFriend(friend)}”的方式是EL 2.2。您可以通过执行以下步骤来解决此问题:http://www.mkyong.com/jsf2/how-to-pass-parameters-in-method-expression-jsf-2-0/或使用此处所述的其他方式:http://www.mkyong.com/jsf2/4-ways-to-pass-parameter-from-jsf-page-to-backing-bean/。祝你好运!

答案 2 :(得分:1)

如果您使用的是Tomcat,则可以执行以下操作。

xhtml文件中,您可以执行以下操作。

#{ItemInformationController.setFindItem(525)}
#{ItemInformationController.findItem}" var="AVar">

控制器文件中,您可以执行以下操作:

int itemId;

public List<Item> getFindItem() {
    return getJpaController().findLevel3Item(levelId);
}

public void setFindItem(int id) {
    itemId= id;
}

这可以找到Tomcat 6/7 ...

答案 3 :(得分:0)

enter code here


@ManagedBean(name = "customerBean")
    @SessionScoped
    public class CustomerBean implements Serializable {
        /**/
        private static final long serialVersionUID = 1L;
        CustomerManager customerManager = CustomerManager.getInstance();


        private Book book;
        private Long id;
        private String name, vorname, addresse, ort;

        Customer customer = new Customer();
        ArrayList<Customer> customerList;

        public void findCustomer(String name){
            CustomerManager.getInstance().findCustomerByName(name);
        System.out.println("Hello" + customer.getName());

        }

    getters and setters...




     public class CustomerManager {
            static EntityManagerFactory emf;
            static EntityManager em;
            static CustomerManager instance;
            EntityTransaction entityTransaction = null;

            public CustomerManager() {
                emf = Persistence.createEntityManagerFactory("customerRegistration");
                em = emf.createEntityManager();
            }

            List<Customer> customerstList = new ArrayList<Customer>();
            Book book = new Book();
            Set<Book> bookList = new HashSet<Book>();

            Customer customer = new Customer();
    public void findCustomerByName(String name) {   
            // Query for a single object.
            Query query = em.createQuery("Select c FROM Customer c WHERE c.name = :name");
            query.setParameter("name", name);
            System.out.println("Hello from Business");
            customer = (Customer)query.getSingleResult();


                  }



    <ui:define name="content">
            <h:body>

                <h:form id="main">
                    <p:panelGrid columns="2">
                        <p:outputLabel for="name" value="#{texts.name}" />
                        <p:inputText id="name" value="#{customerBean.customer.name}" />


                        <h:commandButton value="Search"
                            action="#{customerBean.findCustomer()}" />
                    </p:panelGrid>
                </h:form>

            </h:body>
        </ui:define>