Help

Controls

PermLinkWikiLink

Built with Seam

You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.

Forum: Seam Users Forum ListTopic List
01. Sep 2008, 22:29 America/New_York | Link

Hi all, i have a problema with lazy loading i think.

I have an ordinary entity that have a collection of items, the getItems() method is annotated with fetchType.Lazy, the problem is that when i persist an item an go back to the entity detail page, and click on the tab that shows the list of items assosiated with the entity, the list is returning empty, nevertheless if i go to the menu bar(my project is a seam-gen generated one) and click on the entityList option, everything works just fine, the tab shows the collection of items without problem. There is another clue, if i go again and add another item and go back to the entity detail page i get the tab showing the collection minus the last item that was persisted.

Somebody can explain me this behavior.

This is my code: the entity class:

package com.prueba.domain;

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

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import org.hibernate.validator.NotNull;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.Name;


@Name("expediente")
@Entity
@Table (name="EXPEDIENTE")
public class Expediente {
        
        private Long id;
    private String nroExpediente;
    private List<Testigo> testigos = new ArrayList<Testigo>();
    private List<Acusado> acusados = new ArrayList<Acusado>();
    
    
    @OneToMany(cascade = CascadeType.ALL ,fetch = FetchType.LAZY, mappedBy="expediente")
    public List<Acusado> getAcusados() {
                return acusados;
        }

        public void setAcusados(List<Acusado> acusados) {
                this.acusados = acusados;
        }

        @Column (name="nroExpediente", nullable = false)
    @NotNull
        public String getNroExpediente() {
                return nroExpediente;
        }

        public void setNroExpediente(String nroExpediente) {
                this.nroExpediente = nroExpediente;
        }

        @Id
        @GeneratedValue
        public Long getId() {
                return id;
        }

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

        @OneToMany(cascade=CascadeType.ALL,fetch = FetchType.LAZY, mappedBy = "expediente")
        public List<Testigo> getTestigos() {
                return testigos;
        }

        public void setTestigos(List<Testigo> testigoLista) {
                this.testigos = testigoLista;
        }

}

The item class:

package com.prueba.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;

import org.hibernate.validator.NotNull;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.web.RequestParameter;

@Name("acusado")
@Entity
@PrimaryKeyJoinColumn(name="PERSONA_ID")
@Table (name="ACUSADO")
public class Acusado extends Persona {
        
        private String descripcionFisica;
        private Expediente expediente;


        @ManyToOne (fetch = FetchType.LAZY)
        @JoinColumn(name="Expediente_ID",nullable = false)
        public Expediente getExpediente() {
                return expediente;
        }

        public void setExpediente(Expediente expediente) {
                this.expediente = expediente;
        }

        @Column (name="descripcionFisica", nullable = false)
    @NotNull
        public String getDescripcionFisica() {
                return descripcionFisica;
        }

        public void setDescripcionFisica(String descripcionFisica) {
                this.descripcionFisica = descripcionFisica;
        }
        


}

The entityHome class:

package com.prueba.facade;

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

import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Begin;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.Transactional;
import org.jboss.seam.annotations.web.RequestParameter;
import org.jboss.seam.framework.EntityHome;

import com.prueba.domain.Acusado;
import com.prueba.domain.Expediente;

@Name("expedienteHome")
public class ExpedienteHome extends EntityHome<Expediente> {

        @RequestParameter
        Long expedienteId;
        
        @Out 
        List<Acusado> listaAcusados = new ArrayList<Acusado>();

        @Override
        public Object getId() {
                if (expedienteId == null) {
                        return super.getId(); 
                } else {
                        return expedienteId;
                }
        }

        @Override
        @Begin
        public void create() {
                super.create();

        }

        @Transactional
        public List<Acusado> getAcusados() {
                if (getInstance() == null)
                        return null;
                else {
                        Object lista = getInstance().getAcusados();
                        this.listaAcusados = (List<Acusado>)lista;
                        return (List<Acusado>)lista;
                }
        }

}

The itemAction class:

package com.prueba.facade;

import java.io.Serializable;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;

import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Begin;
import org.jboss.seam.annotations.Conversational;
import org.jboss.seam.annotations.FlushModeType;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.Transactional;
import org.jboss.seam.annotations.web.RequestParameter;
import org.jboss.seam.core.Events;
import org.jboss.seam.log.Log;
import org.jboss.seam.faces.FacesMessages;

import com.prueba.domain.Acusado;
import com.prueba.domain.Expediente;

@Name("registerAcusadoAction")
@Scope(ScopeType.CONVERSATION)
public class RegisterAcusadoAction implements Serializable{

        @Logger
        private Log log;
        @In
        FacesMessages facesMessages;
        @In
        private EntityManager entityManager;
        
        @RequestParameter
        String kaka;
        
        @RequestParameter
        String returnTo = "testigoList.xhtml";
        
        String from = "/acusadoList.xhtml";

        @Out(required = false) Acusado acusado;
        
        @In (create = true)
        ExpedienteHome expedienteHome;


        @Transactional
        @Begin(join=true)
        public void registerAcusado(Acusado acusadoLocal) {
                acusadoLocal.setExpediente(expedienteHome.getInstance());
                entityManager.persist(acusadoLocal);
                entityManager.flush();
                acusado = acusadoLocal;
                Events.instance().raiseTransactionSuccessEvent("EntidadCRUD","Acusado Registrado", "RegisterAcusadoAction.registerAcusado");
        }

        
        public void updateAcusado(Acusado acusadoLocal) {
                boolean bol1 = entityManager.contains(acusadoLocal);
                entityManager.flush();
//              Events.instance().raiseTransactionSuccessEvent("EntidadCRUD","Acusado Actualizado", "RegisterAcusadoAction.updateAcusado");
        }

        @Transactional
        public void loadAcusado() { 
                Events.instance().raiseTransactionSuccessEvent("EntidadCRUD","", "RegisterAcusadoAction.loadAcusado");
                if (kaka != null ) {   
                        try {
                                acusado = (Acusado) entityManager.find(Acusado.class, kaka);
                        } catch (NoResultException nre) {
                        } catch (NonUniqueResultException nure) {
                        }
                }else
                {
                        boolean bol1 = entityManager.contains(Component.getInstance("acusado"));
                        if (acusado == null){
                                acusado = new Acusado();
                                log.info("El acusado vino null");
                        }
                }
                
                boolean bol = entityManager.contains(acusado);
        }
        

        public void verPaginaRetorno()
        {
                        if (returnTo != null)
                                from = returnTo;
        }

        public void cleanVar(String varName){
                org.jboss.seam.contexts.Contexts.getConversationContext().remove(varName);
        }
        

        public String getReturnTo() {
                return returnTo;
        }


        public void setReturnTo(String returnTo) {
                this.returnTo = returnTo;
        }


        public String getFrom() {
                return from;
        }


        public void setFrom(String from) {
                this.from = from;
        }

}

the entity detail page:

<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
                             "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
        xmlns:s="http://jboss.com/products/seam/taglib"
        xmlns:ui="http://java.sun.com/jsf/facelets"
        xmlns:f="http://java.sun.com/jsf/core"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:rich="http://richfaces.org/rich" template="layout/template.xhtml">

        <ui:define name="body">

                <h:messages globalOnly="true" styleClass="message" />

                <h:form id="expedienteForm">

                        <rich:panel>
                                <f:facet name="header">expediente</f:facet>

                                <s:decorate id="nameDecoration" template="layout/edit.xhtml">
                                        <ui:define name="label">Numero de expediente</ui:define>
                                        <h:inputText id="nro" required="true"
                                                value="#{expedienteHome.instance.nroExpediente}" />
                                </s:decorate>

                                <div style="clear: both" />

                        </rich:panel>

                        <div class="actionButtons"><h:commandButton id="save"
                                value="Salvar" action="#{expedienteHome.persist}"
                                rendered="#{!expedienteHome.managed}" /> <h:commandButton
                                id="update" value="Actualizar" action="#{expedienteHome.update}"
                                rendered="#{expedienteHome.managed}" /> <h:commandButton
                                id="delete" value="Eliminar" action="#{expedienteHome.remove}"
                                immediate="true" rendered="#{expedienteHome.managed}" /> <s:button
                                propagation="end" id="expedienteDone" value="Terminar"
                                view="/expedienteList.xhtml" /></div>

                        <rich:panel>
                                <rich:tabPanel id="expCollections">
                                        
                                        <rich:tab id="acusadosTab" label="Acusados">

                                                <!--                                                 <h:messages globalOnly="true" styleClass="message" />  -->

                                                <rich:panel>
                                                        <f:facet name="header">Listado de acusados para el expediente actual</f:facet>

                                                        <div class="results"><h:outputText
                                                                value="No existen acusados asociados a este expediente aun"
                                                                rendered="#{empty expedienteHome.getAcusados()}" /> <h:dataTable
                                                                id="acusadoList" var="acusado" value="#{listaAcusados}"
                                                                rendered="#{not empty listaAcusados}" cellpadding="2"
                                                                rowClasses="graybg,whitebg">
                                                                <h:column>
                                                                        <f:facet name="header">CI</f:facet>
                    #{acusado.ci}
                </h:column>

                                                                <h:column>
                                                                        <f:facet name="header">Nombre</f:facet>
                                                                        <s:link id="nombreLink" value="#{acusado.nombre}"
                                                                                view="/registerAcusado.xhtml" propagation="join">
                                                                                <f:param name="returnTo" value="/expediente.xhtml" />
                                                                    </s:link>
                                                                </h:column>

                                                                <h:column>
                                                                        <f:facet name="header">Direccion</f:facet>
                    #{acusado.direccionParticular}
                </h:column>

                                                                <h:column>
                                                                        <f:facet name="header">Desc Fisica</f:facet>
                    #{acusado.descripcionFisica}
                                </h:column>

                                                        </h:dataTable></div>

                                                </rich:panel>

                                                <div class="actionButtons"><s:button id="acusadoDone"
                                                        value="Create acusado" view="/registerAcusado.xhtml">
                                                        <f:param name="returnTo" value="/expediente.xhtml" />
                                                </s:button></div>

                                        </rich:tab>
                                </rich:tabPanel>
                        </rich:panel>
                </h:form>

        </ui:define>

</ui:composition>

6 Replies:
02. Sep 2008, 00:05 America/New_York | Link

private EntityManager entityManager;

This is not in extended mode... should it be?

 

But I being poor have only my dreams. I have spread my dreams under your feet. Tread softly because you tread on my dreams...

05. Sep 2008, 19:58 America/New_York | Link

Hi, yes i am using am extended managed persistence context because i am using a seam managed persistence context that is injected via the @In annotation.

I can´t figured out what can be the problem. Any idea or suggestion will be very appreciated...

08. Sep 2008, 15:08 America/New_York | Link

Try changing this -

   @ManyToOne (fetch = FetchType.LAZY)
        @JoinColumn(name="Expediente_ID",nullable = false)
        public Expediente getExpediente() {
                return expediente;
        }




  
@ManyToOne (fetch = FetchType.EAGER)
        @JoinColumn(name="Expediente_ID",nullable = false)
        public Expediente getExpediente() {
                return expediente;
        }
08. Sep 2008, 16:10 America/New_York | Link

You have to understand that SMPC managed entities are cached in 1st level cache for the duration of the conversation so that

getAcusados
doesn't refresh unless you load your Expediente in a new conversation (SMPC) or explicitely refresh it
EntityManager.refresh(expediente)
.

In your case you can either:

  • End the conversation whenever a new entity is added.
  • I would rather suggest add a method enforcing bidirectional wiring. Create a new Expediente.addAcusado() method and call it when you persist your new Acusados. This will ensure your in-memory Expediente gets updated without having to reload Expediente from the database.
public void addAcusado(Acusado acusado) {
                this.acusados.add(acusado);
                acusado.setExpediente(this);
        }
Rating:  *
18. Sep 2008, 16:24 America/New_York | Link

Hi Guillaume, your advise works great, now it generate several question to me:

Guillaume Jeudy wrote on Sep 08, 2008 16:10:
You have to understand that SMPC managed entities are cached in 1st level cache for the duration of the conversation so that
getAcusados
doesn't refresh unless you load your Expediente in a new conversation (SMPC) or explicitely refresh it
EntityManager.refresh(expediente)
.

I do not understand this very well, because i make a flush() after i invoke the persist method when a new Acusado object is registered, beside that in order to view the list of Acusados from an Expediente instance, i end the conversation where i persist the Acusado and open a new one when i pick up an Expediente from the list page, the Expediente is loaded by its id making a query, ¿why i have to refresh it still?

In your case you can either:

End the conversation whenever a new entity is added.

I end the conversation after several entities are added, and only after that i try to get the list of Acusados of a given Expediente by invoking the lazy method getAcusados()

I would rather suggest add a method enforcing bidirectional wiring. Create a new Expediente.addAcusado() method and call it when you persist your new Acusados. This will ensure your in-memory Expediente gets updated without having to reload Expediente from the database. public void addAcusado(Acusado acusado) { this.acusados.add(acusado); acusado.setExpediente(this); }

I considered that idea but i rejected it because of my feeling of that could lead to a potential lack of memory problem when the number of Acusado objects added to the list grows too much.

Click HELP for text formatting instructions. Then edit this text and check the preview.

18. Sep 2008, 16:44 America/New_York | Link

Hi Guillaume, Sorry for the rating i gived to your answer, it was a bad click trying to rate 5 starts, your answer is very good and help ed me too much, i thank you very much.