Search code examples
weblogiccdientitymanagerejb-3.1stateless

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


My entry point is a @Singleton scheduled to be run twice a minute.

@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();
        }
    }
}

In this Singleton, I inject my OutgoingMessageProvider, a Stateless 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);
    }

        ....

}

When I upload and deploy my war on a weblogic (12.1.3), at the first start, everything is OK and works fine. But when I stop my app and start it up again in the Weblogic Admin Console, I have a "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$13.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

So, can someone explain me why everything works fine when I deploy my app, and goes wrong when I restart ? What happens in the application server when an app starts or stops ?

As we can see in the log, the Singleton knows the provider, so I can only imagine the provider does not know the entity manager... Am I wrong ? But, if I try to inject the EntityManager in the singleton, everything works fine. Then it means that the entityManager are well managed by the app server... So why isn't it injected in the stateless bean ?

I tried to instantiate myself an entitymanager in the provider, by adding a PostConstruct (and removing the @PersistenceContext...) :

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

But this method is called only once, and I have no trace in my log when I restart the app.

Is it normal ?


Solution

  • The problem has been resolved by replacing the @Inject by a @EJB in my singleton :

    @Startup
    @Singleton
    public  class MyScheduledProcess {
    
        @Resource
        protected TimerService timerService;
    
        @EJB
        private OutgoingMessageProvider provider;
    ...
    

    Yes, it seems logic that it works with @EJB.

    But I do not understand the behaviour that I described with @Inject : works fine the first time (after deploy), but injections fail when I stop and start again the war. If someone knows, feel free to share :)