ManagedBean property not found

2019-02-11 07:31发布

问题:

In my webapp, when I click on the login link, the Tomcat webserver throws the following exception:

exception
javax.servlet.ServletException: /aluno_jsf.xhtml: Property 'logout' not found on type
br.com.aluno.controller.LoginMB

javax.faces.webapp.FacesServlet.service(FacesServlet.java:422)

root cause
javax.el.ELException: /aluno_jsf.xhtml: Property 'logout' not found on type
br.com.aluno.controller.LoginMB
[...]

Here's my @ManagedBean:

package br.com.aluno.controller;

import java.io.Serializable;
import java.util.Collection;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;
import br.com.aluno.dao.DaoFactory;
import br.com.aluno.entity.Usuario;
import br.com.aluno.util.JsfUtil;

@ManagedBean
public class LoginMB implements Serializable {
private static final long serialVersionUID = 6667329439219329074L;

private Usuario usuario;

@PostConstruct
public void init() {
    usuario = new Usuario();
}

public void logar() {
    try {
        Collection<Usuario> usuarios = DaoFactory
                .getDAOFactory(DaoFactory.JPA).getUsuarioDao()
                .validarLogin(usuario);
        if (usuarios != null && usuarios.size() == 1) {

            usuario = usuarios.iterator().next();

            HttpSession session = (HttpSession) FacesContext
                    .getCurrentInstance().getExternalContext()
                    .getSession(true);
            if (session != null) {
                session.setAttribute("usuario", usuario);
                session.setAttribute("usuarioTipo", usuario.getClass()
                        .getName());
            }
        } else {
            JsfUtil.addErrorMessage("Login ou senha invalida",
                    "Login ou senha invalida");
        }
    } catch (Exception e) {
        JsfUtil.addFatalMessage("Entre em contato com o administrador",
                e.getMessage());
    }
}

public String logout() {
    HttpSession session = (HttpSession) FacesContext.getCurrentInstance()
            .getExternalContext().getSession(false);
    if (session != null) {
        session.invalidate();
    }
    return "/login?faces-redirect=true";
}

public Usuario getUsuario() {
    return usuario;
}

public void setUsuario(Usuario usuario) {
    this.usuario = usuario;
}
}

I have a link in a index.html which redirects to the following login.xhtml:

<ui:decorate 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:p="http://primefaces.org/ui" template="/aluno_jsf.xhtml">

<ui:define name="conteudo">
    <h:form rendered="#{sessionScope.usuario == null}">
        <h3>Login</h3>
        <p:messages id="messages" showDetail="true" autoUpdate="true" />
        <h:panelGrid columns="2">
            <p:outputLabel for="login" value="Login:" />
            <p:inputText id="login" value="#{loginMB.usuario.login}" required="true" 
requiredMessage="Digite um login" />
            <p:outputLabel for="senha" value="Senha:" />
            <p:password id="senha" value="#{loginMB.usuario.senha}" required="true" 
requiredMessage="Digite uma senha" />
            <p:commandButton action="#{loginMB.logar}" value="Logar" ajax="false" />
        </h:panelGrid>
    </h:form>
</ui:define>

After validation, the following pages should be rendered:

<!DOCTYPE html>
<html 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:p="http://primefaces.org/ui" >
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>aluno_jsf</title>
</h:head>
<h:body>
<f:view>
    <h:form>
        <p:menubar
            rendered="#{sessionScope.usuarioTipo == 'br.com.aluno.entity.Administrador'}">
            <p:menuitem url="/administrador/cadastroCurso.xhtml"
value="Cadastro de curso" />
            <p:menuitem url="/administrador/cadastroDisciplina.xhtml" 
value="Cadastro de disciplinas" />
            <p:menuitem url="/administrador/cadastroAluno.xhtml" 
value="Cadastro de alunos" />
            <p:menuitem url="/administrador/atribuiNota.xhtml" 
value="Atribuicao de notas para alunos" />
            <p:menuitem action="#{loginMB.logout}" value="Logout" />
        </p:menubar>
        <p:menubar
rendered="#{sessionScope.usuarioTipo == 'br.com.aluno.entity.Aluno'}">
            <p:menuitem url="/aluno/nota.xhtml" value="Consulta de notas" />
            <p:menuitem url="/aluno/senha.xhtml" value="Alteracao de senha" />
            <p:menuitem action="#{loginMB.logout}" value="Logout" />
        </p:menubar>
    </h:form>
    <ui:insert name="conteudo">
    conteudo
    </ui:insert>
</f:view>
</h:body>
</html>

Since I'm adapting this web app - and I've already got some misconfigurations before - does anyone knows what's happening now?

Thanks in advance.

As you asked, her's the new exception:

message Could not initialize class br.com.fiap.aluno.util.JpaUtil

description The server encountered an internal error (Could not initialize class     br.com.fiap.aluno.util.JpaUtil) that prevented it from fulfilling this request.

exception

javax.servlet.ServletException: Could not initialize class br.com.fiap.aluno.util.JpaUtil
javax.faces.webapp.FacesServlet.service(FacesServlet.java:422)

root cause

java.lang.NoClassDefFoundError: Could not initialize class br.com.fiap.aluno.util.JpaUtil
br.com.fiap.aluno.dao_jpa.JpaUsuarioDao.validarLogin(JpaUsuarioDao.java:46)
br.com.fiap.aluno.controller.LoginMB.logar(LoginMB.java:30)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:601)
javax.el.BeanELResolver.invoke(BeanELResolver.java:484)
javax.el.CompositeELResolver.invoke(CompositeELResolver.java:161)
org.apache.el.parser.AstValue.getValue(AstValue.java:159)
org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:189)
com.sun.faces.facelets.el.ELText$ELTextVariable.toString(ELText.java:214)
com.sun.faces.facelets.compiler.AttributeInstruction.write(AttributeInstruction.java:89)
com.sun.faces.facelets.compiler.UIInstructions.encodeBegin(UIInstructions.java:82)
    com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:302)
com.sun.faces.renderkit.html_basic.GridRenderer.renderRow(GridRenderer.java:185)
com.sun.faces.renderkit.html_basic.GridRenderer.encodeChildren(GridRenderer.java:129)
javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:1756)
javax.faces.render.Renderer.encodeChildren(Renderer.java:168)
javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:1756)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:1759)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:1759)
  com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:401)
com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121)
com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:410)

note The full stack trace of the root cause is available in the Apache Tomcat/7.0.29 logs.

I'll try to fix it, but I appreciate if you could give some hints.

回答1:

javax.el.ELException: /aluno_jsf.xhtml: Property 'logout' not found on type br.com.aluno.controller.LoginMB

This suggests that the #{loginMB.logout} is been evaluated as a ValueExpression instead of as a MethodExpression.

That can for example happen if you're using <h:outputText value="#{loginMB.logout}" />, or even when the x namespace behind <x:someComponent action="#{loginMB.logout}" /> can't be resolved due to missing or incorrect XML namespace declaration or the JAR file containing the components not being included in the runtime classpath.

The cause is not visible in the code posted so far, but with my best guess you're not using Facelets templating properly. The code shows strange use case of <ui:decorate>. Head to this answer to learn how to properly use template compositions: How to include another XHTML in XHTML using JSF 2.0 Facelets?



回答2:

Logout isn't a property accessor, it's a method.

Try this: #{loginMB.logout()} instead



回答3:

I had the same issue , and I solved it by removing comments that I added to my xhtml file

Solution found on this page



回答4:

I would like to offer some reasons why you might get javax.el.ELException on a EL Method reference in xhtml. Consider this a matter of reference, maybe others will continue to contribute.

Mismatch of Java EE versions

  • The Java EE version running on your AppServer. This should be part of your AppServer documentation, or if you customized it (like building your own on top of tomcat), you should know.
  • The tag libraries used, which can be identified with the xmlns used in your <html> tag.

Example, if you are using Java EE 6, then this is wrong:

<html 
  xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://xmlns.jcp.org/jsf/html">

And should be instead

<html 
  xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html">

Note the use of sun.com instead of jcp. You should use jcp for Java EE 7 upward.

Note that similar issues exist for <persistence> in persistence.xml, and <beans> in beans.xml!

Tag Attribute that does not support MethodExpression

Research the documentation for the Tag Library, for the exact version you are using. You will have a few possibilities:

  1. The tag attribute is not included in the specification. This can be possibly because it was added only in a later version of the tag library. In that case, the code will assume that it is a regular property, and will be evaluated during the rendering phase as a regular property (looking for a getter). This is also the reason behind the failure in case of Java EE version mismatch.
  2. The tag attribute is documented, but it is not specified that it 'must evaluate to javax.el.MethodExpression'. In that case it expects the supplied property to be of a different type and try to evaluate it as such. In case a Method is supplied it has to be with the () syntax, and the method will be executed only to retrieve the expected type.
  3. the tag attribute is documented, but it is not documented as of type javax.el.ValueExpression, in which case it does not even accept an Expression in EL syntax, and evaluation will happen immediately and only during rendering.

For this particular question, we can refer to the PrimeFaces 3.4 Tag Documentation. It is unfortunate that the exact version used is not provided.

EL Implementation does not support Method References

In this case, method references without () will by default interpreted as regular properties, and try to access getters/setters.



标签: jsf el