Search code examples
jsfjsf-2viewparams

<f:viewParam> javax.persistence.NoResultException: No entity found for query


I have a grid where the user can see his records, when he clicks on a record it links to another page so he can edit or delete it.

The record in that page shows correctly, and it has a button to update the record if any changes where made and getting the user back to the grid.

I am working with Java 1.8 with Primefaces, on Netbeans 8.0.2 and wildfy 8.2 and my OS is UBUNTU.

When I try to change something, the pages just does nothing and I have this record in the wildfly log

15:11:16,369 ERROR [org.jboss.as.ejb3] (default task-19) javax.ejb.EJBTransactionRolledbackException: No entity found for query 15:11:16,371 ERROR [org.jboss.as.ejb3.invocation] (default task-19) JBAS014134: EJB Invocation failed on component GastoDAOImpl for method public abstract dominio.Gasto persistencia.GastoDAO.getGastoporID(int): javax.ejb.EJBTransactionRolledbackException: No entity found for query

Caused by: javax.persistence.NoResultException: No entity found for query

15:11:16,405 ERROR [org.jboss.as.ejb3.invocation] (default task-19) JBAS014134: EJB Invocation failed on component GastoControladorImpl for method public abstract dominio.Gasto controladores.GastoControlador.obtenerGastoporID(int): javax.ejb.EJBTransactionRolledbackException: No entity found for query

15:11:16,439 SEVERE [javax.enterprise.resource.webcontainer.jsf.context] (default task-19) javax.faces.component.UpdateModelException: javax.el.ELException: /editargastos.xhtml @10,64 value="#{gastoBean.idGasto}": javax.ejb.EJBTransactionRolledbackException: No entity found for query

The weird thing is that if I run the program in debug mode, there are no problems at all and the system just works as intended (the data is properly modified and the user just gets back to the main grid.

My code:

1) This is the page that shows the record for the item that will be modified it shows the correct record in debug mode or normal mode

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:f="http://xmlns.jcp.org/jsf/core"
      xmlns:p="http://primefaces.org/ui"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
    <h:head>
        <f:metadata>
            <f:viewParam name="id_gasto" value="#{gastoBean.idGasto}"/>
        </f:metadata>

        <title>Gaston editar un gasto</title>
    </h:head>
    <h:body>
        <div id="header">
            <ui:insert name="header">
                <ui:include src="defaultHeader.xhtml" />
            </ui:insert>  
        </div>

        <h2>Editar un gasto  Propietario: #{loginBean.usuario.apellido}</h2>
        <h3>Familia: #{loginBean.usuario.familia.nombre}</h3>

        <h:form>
            <h:messages></h:messages>
            <p:panelGrid columns="2">
                <h:outputText value=" Fecha de pago" />     
                <p:calendar value="#{gastoBean.gasto.fecha_registro}" required="true"/>
                <h:outputText value=" Moneda" />     
                <h:selectOneMenu id="moneda" value="#{gastoBean.gasto.moneda}" >
                    <f:selectItems value="#{gastoBean.monedas}"></f:selectItems>
                </h:selectOneMenu>
                <h:outputText value="Monto" />   
                <h:inputText value="#{gastoBean.gasto.monto}" required="true"/>
                <h:outputText value=" Descripcion" />     
                <h:inputText value="#{gastoBean.gasto.descripcion}" required="true"/>
                <h:outputText value=" Clasificacion" />     
                <h:inputText value="#{gastoBean.gasto.clasificacion}" required="true"/>

            </p:panelGrid>
            <br></br>

            <p:commandButton action="#{gastoBean.modificarGasto()}" value="Modificar gasto" />
            <p:commandButton action="#{gastoBean.eliminarGasto(id_gasto)}" value="Eliminar gasto" />

            <br></br>
            <h:outputText value="#{gastoBean.mensaje}"  />
            <br></br><br></br>
            <hr></hr>
            <small>Todos los campos son obligatorios</small>
        </h:form>
    </h:body>
</html>

2) Backing bean: This is the bean called by the modify item in the previous page, when the systems runs in debug mode I can see that every single line works as intended and after completition the database is updated and the user is send to the grid.

But... if I run the program without the debug option it just not work at all, nor database modification, nor user redirection and nor exception is shown.

public void modificarGasto() {
    try {
        controlador.modificarGasto(gasto);
        Familia f = this.autenticado.getUsuario().getFamilia();
        this.listaGastos = controlador.obtenerGastosFamiliaporID(f.getId_familia());
        ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();

        ec.redirect("listadog.xhtml");
    } catch (Exception e) {
        this.mensaje = "ERROR: No se pudo guardar el registro";
    }
}

UPDATE: I just modified the method attached to the the button just to give a message and that wont work neither in "normal mode" I am staring to think it is actually an error in Primefaces :(


Solution

  • javax.persistence.NoResultException: No entity found for query

    This particular exception will be thrown when you use JPA Query#getSingleResult() and the query actually didn't return any result. You should be reading the stack trace of the exception to naildown one responsible for calling this method, and to understand why exactly this method is being called at that moment.

    Based on the sparse information provided so far (really, the full stack trace would have explained and answered nearly everything; remember to post the stack trace in its entirety in any question about an exception you couldn't interpret), I can only make an educated guess that you bound the <f:viewParam> to a request scoped bean instead of a view scoped bean, and that it is in some way triggering some code which converts the ID supplied as request parameter to the actual entity using that JPA query with getSingleResult(). When you submit a form in that view, the request scoped bean will be recreated, and the entity will be null, and the <f:viewParam> will run once again, but the initial request parameter is not there anymore.

    Abusing a session scoped bean for view scoped data, as in your attempted answer, is the wrong solution. You need at least a view scoped bean for this. And, depending on the real root cause of the problem, you may need to make some more changes. Hints can be found in the below "See also" links:

    See also