jsfpropertynotfoundexception

The class 'packageName.DonacionBean' does not have the property 'donar' - Action method not detected?


I'm facing an issue with a Java project that uses EJB and JSF, and it's been quite frustrating. I have a simple setup where an XHTML file calls a method defined in a managed bean.

Here's my .xhtml:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
<head>
    <title>Donaciones</title>
</head>
<body>
    <h:form id="donacionForm">
        <h2>Registrar una Donación</h2>
        <p:panelGrid columns="2" cellpadding="5">
            <h:outputLabel for="monto" value="Monto:" />
            <p:inputText id="monto" value="#{donacionBean.monto}" required="true"/>

            <h:outputLabel for="dia" value="Día:" />
            <p:selectOneMenu id="dia" value="#{donacionBean.dia}">
                <f:selectItems value="#{donacionBean.dias}" />
            </p:selectOneMenu>

            <h:outputLabel for="mes" value="Mes:" />
            <p:selectOneMenu id="mes" value="#{donacionBean.mes}">
                <f:selectItems value="#{donacionBean.meses}" />
            </p:selectOneMenu>

            <h:outputLabel for="anio" value="Año:" />
            <p:inputText id="anio" value="#{donacionBean.anio}" required="true"/>

            <h:outputLabel for="moneda" value="Moneda:" />
            <p:selectOneMenu id="moneda" value="#{donacionBean.moneda}">
                <f:selectItem itemLabel="USD" itemValue="USD" />
                <f:selectItem itemLabel="UYU" itemValue="UYU" />
            </p:selectOneMenu>
        </p:panelGrid>
        <p:commandButton value="Agregar Donación" action="#{donacionBean.donar}" update=":donacionForm:donaciones"/>     
                    
        <h2>Lista de Donaciones</h2>
        <p:dataTable value="#{donacionBean.donaciones}" var="donacion">
            <p:column headerText="Monto">
                <h:outputText value="#{donacion.monto}" />
            </p:column>
            <p:column headerText="Moneda">
                <h:outputText value="#{donacion.moneda}" />
            </p:column>
            <p:column headerText="Fecha">
                <h:outputText value="#{donacion.fecha.dia}/#{donacion.fecha.mes}/#{donacion.fecha.anio}" />
            </p:column>
        </p:dataTable>
    </h:form>
</body>
</html>

Here is the corresponding managed bean, DonacionBean.java:

package packageName;

import jakarta.ejb.EJB;
import jakarta.enterprise.context.RequestScoped;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.inject.Named;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Named("donacionBean")
@RequestScoped 
public class DonacionBean {
    
    public DonacionBean() {
        dias = new ArrayList<>();
        meses = new ArrayList<>();
        
        for (int i = 1; i <= 31; i++) 
            dias.add(i);
        for (int i = 1; i <= 12; i++) 
            meses.add(i);
        
    }
    
    private int monto;
    private int dia;
    private int mes;
    private int anio;
    private String moneda;
    private List<Integer> dias;
    List<Integer> meses;
    private Set<DTDonacion> donaciones;
    
    @EJB
    private packageName.DonacionServiceRemote donacionService;

    public String donar() {
        try {
            DTFecha fecha = new DTFecha(dia, mes, anio);
            TipoMoneda tipoMoneda = TipoMoneda.valueOf(moneda.toUpperCase());
            Donacion donacion = new Donacion(monto, fecha, tipoMoneda);

            donacionService.agregarDonacion(donacion);

            // Mensaje de éxito en la interfaz
            FacesContext.getCurrentInstance().addMessage(null, 
                new FacesMessage(FacesMessage.SEVERITY_INFO, "Donación agregada exitosamente", null));
            
            // Resetear campos después de agregar
            monto = 0;
            dia = 1;
            mes = 1;
            anio = 0;
            moneda = null;

            return "result";
        } catch (Exception e) {
            FacesContext.getCurrentInstance().addMessage(null, 
                new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error al agregar donación: " + e.getMessage(), null));
            return "result";
        }
    }

    public List<Integer> getDias() {
        return dias;
    }

    public List<Integer> getMeses() {
        return meses;
    }
    
    public Set<DTDonacion> getDonaciones() {
        this.donaciones = donacionService.obtenerDonaciones();
        return donaciones;
    }

    // Getters y setters para los campos de entrada
    public int getMonto() {
        return monto;
    }

    public void setMonto(int monto) {
        this.monto = monto;
    }

    public int getDia() {
        return dia;
    }

    public void setDia(int dia) {
        this.dia = dia;
    }

    public int getMes() {
        return mes;
    }

    public void setMes(int mes) {
        this.mes = mes;
    }

    public int getAnio() {
        return anio;
    }

    public void setAnio(int anio) {
        this.anio = anio;
    }

    public String getMoneda() {
        return moneda;
    }

    public void setMoneda(String moneda) {
        this.moneda = moneda;
    }
    
}

However, when I try to access the XHTML page via the browser, I get the following error:

An Error Occurred:
/pages/donacion.xhtml: The class 'packageName.DonacionBean' does not have the property 'getDonar'.

This has been driving me crazy. Interestingly, if I rename the method donar to getDonar, the error goes away, but of course, the logic doesn't work as expected.

Any ideas on why the method donar in DonacionBean is causing this problem? I'm using Eclipse and Wildfly, if it helps.

I even tried a similar example within the same project, and it works perfectly:

Here's the working example with UserBean.java:

package packageName;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Named;

@Named("userBean")
@RequestScoped
public class UserBean {
    private String name;
    private String email;

    public UserBean() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    // Action method
    public String submit() {
        System.out.println("Name: " + name);
        System.out.println("Email: " + email);
        return "result";
    }
}

And its corresponding user.xhtml:


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
<h:head>
    <title>User form</title>
</h:head>
<h:body>
    <h:form>
        <h:panelGrid columns="2">
            <h:outputLabel value="Name:" for="name" />
            <h:inputText id="name" value="#{userBean.name}" />

            <h:outputLabel value="Email:" for="email" />
            <h:inputText id="email" value="#{userBean.email}" />

            <h:commandButton value="Send" action="#{userBean.submit}" />
        </h:panelGrid>
    </h:form>
</h:body>
</html> 

result.xhtml:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
<h:head>
    <title>Result</title>
</h:head>
<h:body>
    <h1>Thanks!</h1>
    <h:outputText value="Name: #{userBean.name}" />
    <br />
    <h:outputText value="Email: #{userBean.email}" />
</h:body>
</html>

The action method is invoked without any issues.

Thanks!


Solution

  • Changed <head> to <h:head> and <body> to <h:body> (and the closing tags, of course), and all <p:something> tags for <h:something> and it worked.

    I'm still wondering though, why the <p:something> tags didn't work.