SEAM(2.2.2)アプリケーションでレイジー初期化例外の問題が発生しています。ここのドキュメントで説明されているSEAM管理の永続コンテキスト(JPAを使用)を使用しています
SEAMDocsRef。9.3.1JPAを使用したSEAMマネージド永続コンテキスト
これにより、エンティティマネージャーは私のGenericDAOクラスで@Inを使用して注入されます
シナリオ:
現在ログインしているユーザーエンティティ(セッションスコープ)を挿入する会話スコープのBeanがありますが、ページのJSF(el)を介して追加のユーザー属性を遅延ロードしようとすると、LIEがスローされるようです。
スタックトレースエラー:
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
最初は会話がタイムアウトしたのではないかと思いましたが、これはLIEをスローするのではなく、ユーザーをログアウトすることで処理されます。
では、ユーザーエンティティがセッションスコープから挿入され、アクションBeanが会話スコープであるために、オブジェクトがエンティティマネージャーから何らかの形で切り離されているのではないかと思いました。
残念ながら、例外が毎回スローされるわけではないため、簡単に再現することはできません(アプリケーションはライブであるため、いつでもエラーが発生します)
EAGERLYをロードするようにユーザープロパティを設定することでこれを解決できることはわかっていますが、最初にこれの一番下に行きたいので、すべてのエンティティを前もってロードしたくないです
私のセットアップの詳細:
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
}