EJB 3.0のSession BeanでEntityManagerを使う
メモ
■環境
- WebLogic 11g Release 1
■やりたい事
EJB 3.0のSession Beanの中で、Entity Managerを使ってEntityオブジェクトを扱う。
■基礎
以下の感じで、Session BeanにEntityManagerを注入(DIをあまり理解していないので、用語がおかしかったら訂正して下さい)。
@Stateless public class FooBean implements FooBeanLocal { @PersistenceContext private EntityManager em; // 以下略
createEntityManagerFactoryとか使う必要なし。で、以下のように普通に使おうとしたら
em.getTransaction();
以下のようなExceptionが出た。
<2010/12/15 15時58分37秒 JST> <Error> <HTTP> <BEA-101020> <[ServletContext@3559716[app:projfoo-ear module:projfoo-web path:/projfoo-web spec-version:2.5]]サーブレットは例外により失敗しました javax.ejb.EJBException: EJB Exception: : java.lang.IllegalStateException: The method public abstract javax.persistence.EntityTransaction javax.persistence.EntityManager.getTransaction() cannot be invoked in the context of a JTA EntityManager. at weblogic.deployment.BasePersistenceContextProxyImpl.validateInvocation(BasePersistenceContextProxyImpl.java:121) at weblogic.deployment.BasePersistenceContextProxyImpl.invoke(BasePersistenceContextProxyImpl.java:86) at weblogic.deployment.TransactionalEntityManagerProxyImpl.invoke(TransactionalEntityManagerProxyImpl.java:91) at weblogic.deployment.BasePersistenceContextProxyImpl.invoke(BasePersistenceContextProxyImpl.java:80) at weblogic.deployment.TransactionalEntityManagerProxyImpl.invoke(TransactionalEntityManagerProxyImpl.java:26) at $Proxy160.getTransaction(Unknown Source) at com.example.projfoo.ejb.Foo.start(Foo.java:41) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at com.bea.core.repackaged.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:310) at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182) at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149) at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131) at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119) at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) at com.bea.core.repackaged.springframework.jee.spi.MethodInvocationVisitorImpl.visit(MethodInvocationVisitorImpl.java:37) at weblogic.ejb.container.injection.EnvironmentInterceptorCallbackImpl.callback(EnvironmentInterceptorCallbackImpl.java:54) at com.bea.core.repackaged.springframework.jee.spi.EnvironmentInterceptor.invoke(EnvironmentInterceptor.java:50) at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) at com.bea.core.repackaged.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89) at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:131) at com.bea.core.repackaged.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:119) at com.bea.core.repackaged.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) at com.bea.core.repackaged.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) at $Proxy161.start(Unknown Source) at com.example.projfoo.ejb.Foo_xm90n4_FooLocalImpl.start(Foo_xm90n4_FooLocalImpl.java:244) at com.example.projfoo.servlets.FooServlet.doGet(FooServlet.java:53) at javax.servlet.http.HttpServlet.service(HttpServlet.java:707) at javax.servlet.http.HttpServlet.service(HttpServlet.java:820) at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227) at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125) at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:300) at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:183) at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.doIt(WebAppServletContext.java:3686) at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3650) at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321) at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:121) at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2268) at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2174) at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1446) at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201) at weblogic.work.ExecuteThread.run(ExecuteThread.java:173) ; nested exception is: java.lang.IllegalStateException: The method public abstract javax.persistence.EntityTransaction javax.persistence.EntityManager.getTransaction() cannot be invoked in the context of a JTA EntityManager. at weblogic.ejb.container.internal.EJBRuntimeUtils.throwEJBException(EJBRuntimeUtils.java:148) at weblogic.ejb.container.internal.BaseLocalObject.handleSystemException(BaseLocalObject.java:849) at weblogic.ejb.container.internal.BaseLocalObject.handleSystemException(BaseLocalObject.java:794) at weblogic.ejb.container.internal.BaseLocalObject.postInvoke1(BaseLocalObject.java:489) at weblogic.ejb.container.internal.BaseLocalObject.__WL_postInvokeTxRetry(BaseLocalObject.java:427) Truncated. see log file for complete stacktrace Caused By: java.lang.IllegalStateException: The method public abstract javax.persistence.EntityTransaction javax.persistence.EntityManager.getTransaction() cannot be invoked in the context of a JTA EntityManager. at weblogic.deployment.BasePersistenceContextProxyImpl.validateInvocation(BasePersistenceContextProxyImpl.java:121) at weblogic.deployment.BasePersistenceContextProxyImpl.invoke(BasePersistenceContextProxyImpl.java:86) at weblogic.deployment.TransactionalEntityManagerProxyImpl.invoke(TransactionalEntityManagerProxyImpl.java:91) at weblogic.deployment.BasePersistenceContextProxyImpl.invoke(BasePersistenceContextProxyImpl.java:80) at weblogic.deployment.TransactionalEntityManagerProxyImpl.invoke(TransactionalEntityManagerProxyImpl.java:26) Truncated. see log file for complete stacktrace >
トランザクションの管理もアノテーションを使って書かなきゃいけないのね。
@TransactionAttribute(REQUIRED) private void writeSomethingToDb() { long pk = 1; SomeEntity e = em.find(SomeEntity.class, pk); e.setSomeField("foo"); em.persist(e); }
TransactionAttributeの種類に関しては、ググった所オフィシャルの情報より先にこちらのブログエントリが出てきたので、とりあえず紹介しておく。