计时器EJB 3.1 +线程池

时间:2015-07-28 15:15:46

标签: java multithreading timer ejb schedule

早上好。我需要实现一个应用程序,每x分钟启动n个任务,每个任务写入MySQL表。我以为我会用以下方法修复它:

  1. EJB计时器
  2. JPA用于在DB上书写
  3. Executors.newFixedThreadPool用于任务管理
  4. 这是我的解决方案。以下类是Timer EJB:

    @Singleton
    public class MyTimerService {
    
       @EJB
       private WorkerPool worker;
    
       @Schedule(second="*", minute="*/3",hour="*", persistent=false)
       public void doWork(){
          worker.execute();
       }
    }
    

    这是Executor的实现:

    public class ThreadExecutor implements Executor{
    
        @Asynchronous
        @Override
        public void execute(Runnable command) {
            ExecutorService executor = Executors.newFixedThreadPool(5);
            executor.execute(command);
        }
      }
    

    并完成,Class运行Thread:

    @Stateless
    public class WorkerPool {
    
       @EJB
       private Executor executor;
    
       @EJB(name = "Dao")
       private IDao dao;
    
       public void execute()  {
    
            try {
               List<Object> info = dao.readTable();
                if (info.size() > 0) {
                   for (int i = 0; i < info.size(); i++) {
                       Object temp = info.get(i);
                       Runnable worker = new WorkerThread(temp, dao);
                       executor.execute(worker);
                   }
                   Thread.sleep(30000);
               }
            } catch (Throwable e) {
               e.printStackTrace();
            }
        }
    

    我部署了我的应用程序服务器Glassfish。这是错误:

    [2015-07-28T17:06:53.995+0200] [glassfish 4.1] [WARNING] [AS-EJB-00056]     [javax.enterprise.ejb.container] [tid: _ThreadID=186 _ThreadName=__ejb-thread-pool12] [timeMillis: 1438096013995] [levelValue: 900] [[
      A system exception occurred during an invocation on EJB BetFinderTimerService, method: public void com.surebetfinder.timer.BetFinderTimerService.doWork()]]
    
    [2015-07-28T17:06:53.996+0200] [glassfish 4.1] [WARNING] [] [javax.enterprise.ejb.container] [tid: _ThreadID=186 _ThreadName=__ejb-thread-pool12] [timeMillis: 1438096013996] [levelValue: 900] [[
    
    javax.ejb.EJBException: javax.ejb.EJBException: javax.ejb.CreateException: Could not create stateless EJB
        at com.sun.ejb.containers.StatelessSessionContainer._getContext(StatelessSessionContainer.java:435)
        at com.sun.ejb.containers.BaseContainer.getContext(BaseContainer.java:2579)
        at com.sun.ejb.containers.BaseContainer.preInvoke(BaseContainer.java:1971)
        at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:210)
        at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88)
        at com.sun.proxy.$Proxy296.execute(Unknown Source)
        at com.surebetfinder.logic.processi.__EJB31_Generated__WorkerPool__Intf____Bean__.execute(Unknown Source)
        at com.surebetfinder.timer.BetFinderTimerService.doWork(BetFinderTimerService.java:19)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1081)
        at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1153)
        at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:4786)
        at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:656)
        at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
        at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608)
        at org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:55)
        at org.jboss.weld.ejb.SessionBeanInterceptor.aroundInvoke(SessionBeanInterceptor.java:52)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
        at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
        at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608)
        at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doCall(SystemInterceptorProxy.java:163)
        at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundTimeout(SystemInterceptorProxy.java:145)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
        at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
        at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:369)
        at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:4758)
        at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:4746)
        at com.sun.ejb.containers.BaseContainer.callEJBTimeout(BaseContainer.java:4051)
        at com.sun.ejb.containers.EJBTimerService.deliverTimeout(EJBTimerService.java:1199)
        at com.sun.ejb.containers.EJBTimerService.access$000(EJBTimerService.java:89)
        at com.sun.ejb.containers.EJBTimerService$TaskExpiredWork.run(EJBTimerService.java:1919)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
    Caused by: javax.ejb.EJBException: javax.ejb.CreateException: Could not create stateless EJB
        at com.sun.ejb.containers.StatelessSessionContainer$SessionContextFactory.create(StatelessSessionContainer.java:700)
        at com.sun.ejb.containers.util.pool.NonBlockingPool.getObject(NonBlockingPool.java:246)
        at com.sun.ejb.containers.StatelessSessionContainer._getContext(StatelessSessionContainer.java:430)
        ... 46 more
    Caused by: javax.ejb.CreateException: Could not create stateless EJB
        at com.sun.ejb.containers.StatelessSessionContainer.createStatelessEJB(StatelessSessionContainer.java:514)
        at com.sun.ejb.containers.StatelessSessionContainer.access$000(StatelessSessionContainer.java:97)
        at com.sun.ejb.containers.StatelessSessionContainer$SessionContextFactory.create(StatelessSessionContainer.java:698)
        ... 48 more
    Caused by: java.lang.IllegalStateException: Exception attempting to inject Remote ejb-ref name=com.surebetfinder.logic.processi.WorkerPool/executor,Remote 3.x interface =java.util.concurrent.Executor,ejb-link=null,lookup=,mappedName=,jndi-name=java.util.concurrent.Executor,refType=Session into class com.surebetfinder.logic.processi.WorkerPool: Lookup failed for 'java:comp/env/com.surebetfinder.logic.processi.WorkerPool/executor' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming}
        at org.glassfish.weld.services.InjectionServicesImpl.aroundInject(InjectionServicesImpl.java:175)
        at org.jboss.weld.injection.InjectionContextImpl.run(InjectionContextImpl.java:46)
        at org.jboss.weld.injection.producer.DefaultInjector.inject(DefaultInjector.java:68)
        at org.jboss.weld.injection.producer.StatelessSessionBeanInjector.inject(StatelessSessionBeanInjector.java:58)
        at org.jboss.weld.injection.producer.ejb.SessionBeanInjectionTarget.inject(SessionBeanInjectionTarget.java:117)
        at org.glassfish.weld.services.JCDIServiceImpl.injectEJBInstance(JCDIServiceImpl.java:257)
        at com.sun.ejb.containers.BaseContainer.injectEjbInstance(BaseContainer.java:1748)
        at com.sun.ejb.containers.StatelessSessionContainer.createStatelessEJB(StatelessSessionContainer.java:475)
        ... 50 more
    Caused by: com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Remote ejb-ref name=com.surebetfinder.logic.processi.WorkerPool/executor,Remote 3.x interface =java.util.concurrent.Executor,ejb-link=null,lookup=,mappedName=,jndi-name=java.util.concurrent.Executor,refType=Session into class com.surebetfinder.logic.processi.WorkerPool: Lookup failed for 'java:comp/env/com.surebetfinder.logic.processi.WorkerPool/executor' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming}
        at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:740)
        at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.inject(InjectionManagerImpl.java:507)
        at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:170)
        at org.glassfish.weld.services.InjectionServicesImpl.aroundInject(InjectionServicesImpl.java:165)
        ... 57 more
    Caused by: javax.naming.NamingException: Lookup failed for 'java:comp/env/com.surebetfinder.logic.processi.WorkerPool/executor' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NamingException: Exception resolving Ejb for 'Remote ejb-ref name=com.surebetfinder.logic.processi.WorkerPool/executor,Remote 3.x interface =java.util.concurrent.Executor,ejb-link=null,lookup=,mappedName=,jndi-name=java.util.concurrent.Executor,refType=Session' .  Actual (possibly internal) Remote JNDI name used for lookup is 'java.util.concurrent.Executor#java.util.concurrent.Executor' [Root exception is javax.naming.NamingException: Lookup failed for 'java.util.concurrent.Executor#java.util.concurrent.Executor' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NameNotFoundException: java.util.concurrent.Executor#java.util.concurrent.Executor not found]]]
        at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:491)
        at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:438)
        at javax.naming.InitialContext.lookup(InitialContext.java:417)
        at javax.naming.InitialContext.lookup(InitialContext.java:417)
        at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:636)
        ... 60 more
    Caused by: javax.naming.NamingException: Exception resolving Ejb for 'Remote ejb-ref name=com.surebetfinder.logic.processi.WorkerPool/executor,Remote 3.x interface =java.util.concurrent.Executor,ejb-link=null,lookup=,mappedName=,jndi-name=java.util.concurrent.Executor,refType=Session' .  Actual (possibly internal) Remote JNDI name used for lookup is 'java.util.concurrent.Executor#java.util.concurrent.Executor' [Root exception is javax.naming.NamingException: Lookup failed for 'java.util.concurrent.Executor#java.util.concurrent.Executor' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NameNotFoundException: java.util.concurrent.Executor#java.util.concurrent.Executor not found]]
        at com.sun.ejb.EjbNamingReferenceManagerImpl.resolveEjbReference(EjbNamingReferenceManagerImpl.java:188)
        at com.sun.enterprise.container.common.impl.ComponentEnvManagerImpl$EjbReferenceProxy.create(ComponentEnvManagerImpl.java:1015)
        at com.sun.enterprise.naming.impl.GlassfishNamingManagerImpl.lookup(GlassfishNamingManagerImpl.java:745)
        at com.sun.enterprise.naming.impl.GlassfishNamingManagerImpl.lookup(GlassfishNamingManagerImpl.java:715)
        at com.sun.enterprise.naming.impl.JavaURLContext.lookup(JavaURLContext.java:159)
        at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:471)
        ... 64 more
    Caused by: javax.naming.NamingException: Lookup failed for 'java.util.concurrent.Executor#java.util.concurrent.Executor' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NameNotFoundException: java.util.concurrent.Executor#java.util.concurrent.Executor not found]
        at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:491)
        at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:438)
        at javax.naming.InitialContext.lookup(InitialContext.java:417)
        at javax.naming.InitialContext.lookup(InitialContext.java:417)
        at com.sun.ejb.EjbNamingReferenceManagerImpl.resolveEjbReference(EjbNamingReferenceManagerImpl.java:183)
        ... 69 more
    Caused by: javax.naming.NameNotFoundException: java.util.concurrent.Executor#java.util.concurrent.Executor not found
        at com.sun.enterprise.naming.impl.TransientContext.doLookup(TransientContext.java:237)
        at com.sun.enterprise.naming.impl.TransientContext.lookup(TransientContext.java:204)
        at com.sun.enterprise.naming.impl.SerialContextProviderImpl.lookup(SerialContextProviderImpl.java:66)
        at com.sun.enterprise.naming.impl.LocalSerialContextProviderImpl.lookup(LocalSerialContextProviderImpl.java:114)
        at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:478)
        ... 73 more
    ]]
    

    我哪里错了?

1 个答案:

答案 0 :(得分:0)

正如加布里埃尔所说,当你写作

   @EJB
   private Executor executor;

您告诉容器,而Executor是EJB本地或远程接口,容器无法在JNDI中查看此接口。

试试这个:

   @EJB
   private ThreadExecutor executor;

请求&#34; no interface&#34;而不是豆的视图。或者,您可以编写自己的ThreadExecutor接口。

(旁白:严格来说,这种行为受EJB 3.1规范第4.9.7-4.9.8节的约束,我不认为你违反了它规定的任何规则,所以这可能是Glassfish的错误行为?)

那就是说,我认为你的ThreadExecutor实现异步创建了一个线程池,然后旋转一个线程来执行工作,我认为这是多余的。为什么不使用WorkerThread方法将@Asynchronous转换为EJB?