javax.el.ELException: Could not find property acti

2019-01-20 12:44发布

问题:

While deploying GAE + primefaces application, I got following error:

com.sun.faces.application.view.FaceletViewHandlingStrategy handleRenderException: Error Rendering View[/CreateEmployee.xhtml]
javax.el.ELException: /CreateEmployee.xhtml: Could not find property saveEmployee in class com.fetchinglife.domain.data.dao.EmployeeRepositoryImpl
    at com.sun.faces.facelets.compiler.AttributeInstruction.write(AttributeInstruction.java:94)
    at com.sun.faces.facelets.compiler.UIInstructions.encodeBegin(UIInstructions.java:82)
    at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:302)
    at com.sun.faces.renderkit.html_basic.GridRenderer.renderRow(GridRenderer.java:185)

Even saveEmployee is already in EmployeeRepositoryImpl class. How is this caused and how can I solve it? Are there any annotations which I have to put extra?

回答1:

Let's rephrase the exception in a general format in order to better understand the cause:

javax.el.ELException: Could not find property doSomething in class com.example.Bean

This exception is literally trying to tell you that the Bean class doesn't have the following method:

public SomeObject getDoSomething() {
    return someObject;
}

(where SomeObject is the type of the doSomething property)

There are several causes for this.

Action method expression is incorrectly interpreted as property value expression

Given the fact that the property name is in your case actually a combination of a verb and noun, a resonable cause is you incorrectly bound an action method to an attribute of some JSF component which actually takes a value expression, not a method expression. E.g. when you accidentally do

<h:commandButton value="#{bean.doSomething}">Save</h:commandButton>

or even

<h:button value="Save" outcome="#{bean.doSomething}" />

instead of

<h:commandButton value="Save" action="#{bean.doSomething}" />

The latter would then expect the following method, which you probably actually have:

public String doSomething() {
    // ...
    return "nextpage";
}

(which can also be declared to return void by the way)

Component is not resolved at all

Another probable cause is that the component is not interpreted as a real component at all, but as "plain text". In other words, when you remove the action attribute and then try to open the JSF page in browser, it'll now load fine, but you will see the whole component unparsed in the generated HTML output (which you can see via rightclick, View Source in browser).

This can have several causes:

  1. The XML namespace of the component is wrong or missing. E.g. in case of PrimeFaces you accidentally used the old PrimeFaces 2.x URI while you're actually using PrimeFaces 3+.

    <html ... xmlns:p="http://primefaces.prime.com.tr/ui">
    
  2. The XML namespace URI contains a typo.

    <html ... xmlns:p="http://primefaecs.org/ui">
    
  3. The XML namespace prefix does not match.

    <html ... xmlns:pf="http://primefaces.org/ui">
    
  4. The XML namespace is totally missing.

    <html ...>
    
  5. The component library is not installed at all. In other words, the JARs containing component library's tag definitions is missing in webapp's /WEB-INF/lib folder.

Either way, all <p:xxx> tag won't be parsed and be considered as template text. But, all EL expressions will still be evaluated (as if you're using <p>#{bean.text}</p>), and they will all behave as ValueExpressions instead of MethodExpressions.

An easy way to recognize the root cause is looking at stack trace. If you're seeing com.sun.faces.facelets.compiler.AttributeInstruction in the stack trace, then it means that the component is interpreted as "plain text". Otherwise you would have seen e.g. org.primefaces.component.commandbutton.CommandButton in the specific case of <p:commandButton>.