当我重新启动应用程序时,EntityManager 未注入 @Stateless EJB

EntityManager not injected in a @Stateless EJB, when I restart the app

我的入口点是一个@Singleton,计划每分钟 运行 两次。

@Startup
@Singleton
public  class MyScheduledProcess {

    @Resource
    protected TimerService timerService;

    @Inject
    private OutgoingMessageProvider provider;

    // If I inject the em here, it is always well injected.
    // @PersistenceContext
    // EntityManager em;

    /**
     * Default startup method that will be called automatically to schedule the task.
     */
    @PostConstruct
    public void onStartup() {
        // To erase all timers which may already exist...
        stopAll();  
        // Schedule
        timerService.createCalendarTimer(getScheduledExpression("* * */30"), new TimerConfig());
    }

    @Timeout
    protected void onTimeout(final Timer timer) {
        process(timer);
    }

    /**
     * Business logic called when the timer is triggered.
     * @param timer 
     */
    public void process(Timer t) {
        logger.info("Start process");

        // When em is injected here, there is no problem. 
        //    OutgoingMessage outMsg = em.find(OutgoingMessage.class, 3L);
        //    logger.info("found:" + outMsg);

        logger.info("provider :" + provider);
        List<OutgoingMessage> findAll = provider.findByStatus("CREATED");
        logger.info("Nb in list : " + findAll.size());

    }

    public static ScheduleExpression getScheduledExpression(String stringRepresentation) {
        ScheduleExpression expression = new ScheduleExpression();

        // [....]

        return expression;
    }

    public void stopAll() {
        for(Timer timer : timerService.getTimers()) {
            logger.debug("Stopping " + timer);
            timer.cancel();
        }
    }
}

在这个单例中,我注入了我的 OutgoingMessageProvider,一个无状态 bean。

@Stateless
public class OutgoingMessageProvider {

    @PersistenceContext(unitName= "DefaultPU")
    protected EntityManager em;

    public List<OutgoingMessage> findByStatus(String status) {

        logger.debug("Value of em : " + em);
        return this.em.createQuery("SELECT m FROM OutgoingMessage m WHERE m.status = :status")
            .setParameter("status", status)
            .getResultList();
    }

    public OutgoingMessage findByMessageId(String messageId) {
        return ........
    }


    public void create(OutgoingMessage entity) {
        em.persist(entity);
    }

        ....

}

当我在 weblogic (12.1.3) 上上传和部署我的 war 时,在第一次启动时,一切正常并且工作正常。 但是当我停止我的应用程序并在 Weblogic 管理控制台中再次启动它时,我有一个 "NoSuchEJBException: Bean is already undeployed." :

22:22:16.216 [[ACTIVE] ExecuteThread: '15' for queue: 'weblogic.kernel.Default (self-tuning)'] INFO  com.poc.schedul.MyScheduledProcess - provider :com.poc.schedul.OutgoingMessageProvider_ek022o_NoIntfViewImpl@6b6bebf1

<11-Sep-2016 22:22:16 o'clock CEST> <Error> <EJB> <BEA-011088> <The following error occurred while invoking the ejbTimeout(javax.ejb.Timer) method of EJB MyScheduledProcess(Application: poc2, EJBComponent: poc.war).
javax.ejb.EJBException: EJB Exception: :   com.oracle.pitchfork.interfaces.LifecycleCallbackException: Failure to invoke public java.lang.Object   org.jboss.weld.ejb.SessionBeanInterceptor.aroundInvoke(javax.interceptor.InvocationContext) throws java.lang.Exception on bean class class org.jboss.weld.ejb.SessionBeanInterceptor with args: [LifecycleEventCallbackInvocationContext(962794227)]
at com.oracle.pitchfork.inject.Jsr250Metadata.invokeLifecycleMethod(Jsr250Metadata.java:379)
at com.oracle.pitchfork.intercept.LifecycleEventCallbackInvocationContext.proceed(LifecycleEventCallbackInvocationContext.java:115)
at com.oracle.pitchfork.intercept.LifecycleEventCallbackInvocationContext.proceed(LifecycleEventCallbackInvocationContext.java:144)
at com.oracle.pitchfork.intercept.InterceptionMetadata.invokeTimeoutMethod(InterceptionMetadata.java:531)
at weblogic.ejb.container.injection.EjbComponentCreatorImpl.invokeTimer(EjbComponentCreatorImpl.java:71)
at weblogic.ejb.container.injection.InjectionBasedEjbComponentCreator.invokeTimer(InjectionBasedEjbComponentCreator.java:152)
at weblogic.ejb.container.manager.BaseEJBManager.invokeTimeoutMethod(BaseEJBManager.java:176)
at weblogic.ejb.container.timer.TimerImpl.timerExpired(TimerImpl.java:340)
at weblogic.timers.internal.TimerImpl.run(TimerImpl.java:304)
at weblogic.work.SelfTuningWorkManagerImpl$WorkAdapterImpl.run(SelfTuningWorkManagerImpl.java:548)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:311)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:263)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedMethodAccessor927.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.oracle.pitchfork.inject.Jsr250Metadata.invokeLifecycleMethod(Jsr250Metadata.java:377)
... 11 more
Caused by: com.oracle.pitchfork.interfaces.LifecycleCallbackException: Failure to invoke timeout method protected void com.poc.schedul.MyScheduledProcess.onTimeout(javax.ejb.Timer) on bean class class com.poc.schedul.MyScheduledProcess_szpi74_Impl with args: [[EJB Timer] id: 44 pk: 1 info: null isAutoCreated: false timer: 1473625336209.6(0) state: 2 ejb: MyScheduledProcess(Application: poc2, EJBComponent: poc.war) Thread: Thread[[ACTIVE] ExecuteThread: '15' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads]]]
at com.oracle.pitchfork.inject.Jsr250Metadata.invokeTimeoutMethodInternal(Jsr250Metadata.java:364)
at com.oracle.pitchfork.intercept.LifecycleEventCallbackInvocationContext.proceed(LifecycleEventCallbackInvocationContext.java:120)
at org.jboss.weld.ejb.SessionBeanInterceptor.aroundInvoke(SessionBeanInterceptor.java:49)
... 15 more
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.oracle.pitchfork.inject.Jsr250Metadata.invokeTimeoutMethodInternal(Jsr250Metadata.java:362)
... 17 more
Caused by: javax.ejb.NoSuchEJBException: Bean is already undeployed.
at weblogic.ejb.container.manager.BaseEJBManager.ensureDeployed(BaseEJBManager.java:131)
at weblogic.ejb.container.manager.BaseEJBManager.preInvoke(BaseEJBManager.java:136)
at weblogic.ejb.container.manager.StatelessManager.preInvoke(StatelessManager.java:138)
at weblogic.ejb.container.internal.BaseLocalObject.getBeanInstance(BaseLocalObject.java:148)
at weblogic.ejb.container.internal.BaseLocalObject.preInvoke(BaseLocalObject.java:105)
at weblogic.ejb.container.internal.BaseLocalObject.__WL_preInvoke(BaseLocalObject.java:70)
at weblogic.ejb.container.internal.SessionLocalMethodInvoker.invoke(SessionLocalMethodInvoker.java:22)
at com.poc.schedul.OutgoingMessageProvider_ek022o_NoIntfViewImpl.findByStatus(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.jboss.weld.util.reflection.SecureReflections.work(SecureReflections.java:267)
at org.jboss.weld.util.reflection.SecureReflectionAccess.run(SecureReflectionAccess.java:52)
at org.jboss.weld.util.reflection.SecureReflectionAccess.runAsInvocation(SecureReflectionAccess.java:137)
at org.jboss.weld.util.reflection.SecureReflections.invoke(SecureReflections.java:263)
at org.jboss.weld.bean.proxy.EnterpriseBeanProxyMethodHandler.invoke(EnterpriseBeanProxyMethodHandler.java:115)
at org.jboss.weld.bean.proxy.EnterpriseTargetBeanInstance.invoke(EnterpriseTargetBeanInstance.java:56)
at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:105)
at com.poc.schedul.OutgoingMessageProvider$Proxy$_$$_Weld$Proxy$.findByStatus(OutgoingMessageProvider$Proxy$_$$_Weld$Proxy$.java)
at com.poc.schedul.MyScheduledProcess.process(MyScheduledProcess.java:90)
at com.poc.schedul.MyScheduledProcess.onTimeout(MyScheduledProcess.java:111)
... 22 more

at weblogic.ejb.container.internal.EJBRuntimeUtils.throwEJBException(EJBRuntimeUtils.java:88)
at weblogic.ejb.container.internal.BaseLocalObject.handleSystemException(BaseLocalObject.java:503)
at weblogic.ejb.container.internal.BaseLocalObject.handleSystemException(BaseLocalObject.java:446)
at weblogic.ejb.container.internal.BaseLocalObject.postInvoke1(BaseLocalObject.java:251)
at weblogic.ejb.container.internal.BaseLocalObject.postInvoke(BaseLocalObject.java:431)
Truncated. see log file for complete stacktrace
Caused By: com.oracle.pitchfork.interfaces.LifecycleCallbackException: Failure to invoke public java.lang.Object org.jboss.weld.ejb.SessionBeanInterceptor.aroundInvoke(javax.interceptor.InvocationContext) throws java.lang.Exception on bean class class org.jboss.weld.ejb.SessionBeanInterceptor with args: [LifecycleEventCallbackInvocationContext(962794227)]
at com.oracle.pitchfork.inject.Jsr250Metadata.invokeLifecycleMethod(Jsr250Metadata.java:379)
at com.oracle.pitchfork.intercept.LifecycleEventCallbackInvocationContext.proceed(LifecycleEventCallbackInvocationContext.java:115)
at com.oracle.pitchfork.intercept.LifecycleEventCallbackInvocationContext.proceed(LifecycleEventCallbackInvocationContext.java:144)
at com.oracle.pitchfork.intercept.InterceptionMetadata.invokeTimeoutMethod(InterceptionMetadata.java:531)
at weblogic.ejb.container.injection.EjbComponentCreatorImpl.invokeTimer(EjbComponentCreatorImpl.java:71)
Truncated. see log file for complete stacktrace
Caused By: java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedMethodAccessor927.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.oracle.pitchfork.inject.Jsr250Metadata.invokeLifecycleMethod(Jsr250Metadata.java:377)
at com.oracle.pitchfork.intercept.LifecycleEventCallbackInvocationContext.proceed(LifecycleEventCallbackInvocationContext.java:115)
Truncated. see log file for complete stacktrace
Caused By: com.oracle.pitchfork.interfaces.LifecycleCallbackException: Failure to invoke timeout method protected void com.poc.schedul.MyScheduledProcess.onTimeout(javax.ejb.Timer) on bean class class com.poc.schedul.MyScheduledProcess_szpi74_Impl with args: [[EJB Timer] id: 44 pk: 1 info: null isAutoCreated: false timer: 1473625336209.6(0) state: 2 ejb: MyScheduledProcess(Application: poc2, EJBComponent: poc.war) Thread: Thread[[ACTIVE] ExecuteThread: '15' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads]]]
at com.oracle.pitchfork.inject.Jsr250Metadata.invokeTimeoutMethodInternal(Jsr250Metadata.java:364)
at com.oracle.pitchfork.intercept.LifecycleEventCallbackInvocationContext.proceed(LifecycleEventCallbackInvocationContext.java:120)
at org.jboss.weld.ejb.SessionBeanInterceptor.aroundInvoke(SessionBeanInterceptor.java:49)
at sun.reflect.GeneratedMethodAccessor927.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
Truncated. see log file for complete stacktrace
Caused By: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.oracle.pitchfork.inject.Jsr250Metadata.invokeTimeoutMethodInternal(Jsr250Metadata.java:362)
Truncated. see log file for complete stacktrace
Caused By: javax.ejb.NoSuchEJBException: Bean is already undeployed.
at weblogic.ejb.container.manager.BaseEJBManager.ensureDeployed(BaseEJBManager.java:131)
at weblogic.ejb.container.manager.BaseEJBManager.preInvoke(BaseEJBManager.java:136)
at weblogic.ejb.container.manager.StatelessManager.preInvoke(StatelessManager.java:138)
at weblogic.ejb.container.internal.BaseLocalObject.getBeanInstance(BaseLocalObject.java:148)
at weblogic.ejb.container.internal.BaseLocalObject.preInvoke(BaseLocalObject.java:105)
Truncated. see log file for complete stacktrace

那么,有人能解释一下为什么我部署我的应用程序时一切正常,而当我重新启动时却出错了吗?当应用程序启动或停止时,应用程序服务器会发生什么情况?

正如我们在日志中看到的那样,Singleton 知道提供者,所以我只能想象提供者不知道实体管理器......我错了吗?但是,如果我尝试在单例中注入 EntityManager,一切正常。那么这意味着 entityManager 由应用服务器很好地管理......那么为什么它不注入到无状态 bean 中?

我尝试通过添加 PostConstruct(并删除 @PersistenceContext...)在提供程序中实例化自己的实体管理器:

@PostConstruct
public void init()
{ 
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("DefaultPU"); 
    em = emf.createEntityManager();  }
    logger.info("ENTITY MANAGER HAS BEEN SET : " +em);
}

但是这个方法只被调用了一次,重启应用程序后我的日志中没有任何痕迹。

正常吗?

问题已通过在我的单例中用@EJB 替换@Inject 得到解决:

@Startup
@Singleton
public  class MyScheduledProcess {

    @Resource
    protected TimerService timerService;

    @EJB
    private OutgoingMessageProvider provider;
...

是的,它与@EJB 一起工作似乎符合逻辑。

但我不明白我用 @Inject 描述的行为:第一次(部署后)工作正常,但当我停止并再次启动时注入失败 war。如果有人知道,请随时分享:)