Pergunta

I am experiencing an issue with Lazy initialization exception in my SEAM (2.2.2) Application, I am using a SEAM managed persistance context (with JPA), described in the documentation here

SEAM Docs Ref. 9.3.1 SEAM Managed Persistance Context with JPA

Whereby the entity manager is injected using @In in my GenericDAO class

Scenario:

I have a conversation scoped bean which injects the currently logged in user entity (session scoped), the LIE seems to be thrown when I attempt to lazily load some additional user attributes via JSF (el) in the page.

Stack trace error:

2012-12-24 15:30:34,661 SEVERE [facelets.viewhandler] (http-0.0.0.0-8080-3) Error Rendering View[/user/settings.xhtml]: javax.el.ELException: /user/settings.xhtml: org.hibernate.LazyInitializationException: could not initialize proxy - no Session

at com.webapp.entities.Client_$$_javassist_29.getLogoUrl

At first I thought maybe the conversation had timed out, but this is handled by logging the user out, not throwing a LIE

So now I thought that maybe because the user entity is being injected from the session scope and the action bean is conversation scoped the object is somehow detached from the entity manager?

Unfortunately the exception is not thrown every time, so I cannot easily reproduce it (the application is live so I am getting the errors through as and when)

I know I can solve this by setting the user properties to load EAGERLY but I want to get to the bottom of this first and would prefer not to load all entities up front

More details on my setup:

components.xml:

<persistence:managed-persistence-context name="entityManager"
    auto-create="true"
    persistence-unit-jndi-name="java:/EntityManagerFactories/appData">  
</persistence:managed-persistence-context>

persistence.xml

<persistence-unit name="AppDatabase">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>java:/appDatasource</jta-data-source>
    <properties>
        <property name="hibernate.connection.datasource" value="java:/appDatasource"/>
        <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
        <property name="jboss.entity.manager.factory.jndi.name" value="java:/EntityManagerFactories/appData"/>
        <property name="hibernate.cache.use_second_level_cache" value="false"/>
        <property name="hibernate.show_sql" value="false"/> 
    </properties>
</persistence-unit>

GenericDAO

public abstract class GenericDAOBean<T>
    implements GenericDAO<T>, Serializable{

private static final long serialVersionUID = 1L;

private Class<T> entityBeanType;

@In private EntityManager em;

@SuppressWarnings("unchecked")
public GenericDAOBean() {
    this.entityBeanType = (Class<T>) ((ParameterizedType) getClass()
                            .getGenericSuperclass()).getActualTypeArguments()[0];
}

/**
 * Set the entity manager to use
 * 
 * @param em
 */
public void setEntityManager(EntityManager em) {
    this.em = em;
}

/**
 * Get the current seam entity manager
 * 
 * @return
 */
 protected EntityManager getEntityManager() {
 //Seam entity manager set this way as of version 2.2.0 
 //can't handle abstract classes and @In doesn't inject
 //into this as a parent class
 EntityManager entityManager = (EntityManager)Component.getInstance("entityManager");
 if (entityManager == null)
     throw new IllegalStateException("Seam EntityManager has not been set on "
     +getEntityBeanType().getClass().getName()+"DAO before usage!");
     return entityManager;
 }

//Further Generic method follow here which are removed for brevity
}
Foi útil?

Solução

if you getting your User entity from action bean try in your action bean

User user=entityManger.find(User.class,User.getId());

this should load it into extended persistance context since it looks like it is detached

Edit after your comment.

You certainly dont do it in your getter method, just do it once in any method preceding your acces to the bean and it will be atached to your extended PC, I'd say do it in @Create method of your action bean. About your last question: has it ever been loaded into Seam-managed persistence contexts which is conversation bound?

Also you should inject your entity manager with '@In EntityManager entityManager' since this is your configuration of a managed persistence context in your application.xml. And if your entity has ever been loaded into EPC within this conversation just that should be enough.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top