【问题标题】:Timer EJB 3.1 + Thread pool定时器 EJB 3.1 + 线程池
【发布时间】:2015-07-28 15:15:45
【问题描述】:

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

  1. EJB 定时器
  2. 用于写入 DB 的 JPA
  3. Executors.newFixedThreadPool 用于任务管理

这是我的解决方案。下面的类是 Timer EJB:

@Singleton
public class MyTimerService {

   @EJB
   private WorkerPool worker;

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

这是执行器的实现:

public class ThreadExecutor implements Executor{

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

完成,运行线程的类:

@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
]]

我哪里错了?

【问题讨论】:

  • @EJB 私有执行器执行器; (执行者不是 EJB)

标签: java multithreading timer ejb schedule


【解决方案1】:

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

   @EJB
   private Executor executor;

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

试试这个:

   @EJB
   private ThreadExecutor executor;

这会请求 bean 的“无接口”视图。或者,您可以编写自己的接口到ThreadExecutor

(旁白:严格来说,此行为受 EJB 3.1 规范第 4.9.7-4.9.8 节的约束,我认为您没有违反其中规定的任何规则,所以这可能是Glassfish 的行为不正确?)

也就是说,我认为您的 ThreadExecutor 实现异步创建了一个线程池并分拆一个线程来执行工作,我认为这是多余的。为什么不直接使用@Asynchronous 方法将WorkerThread 变成EJB?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-07
    • 2015-11-20
    • 2016-11-09
    • 2016-01-08
    • 2012-01-03
    • 2014-07-09
    • 2012-01-30
    • 1970-01-01
    相关资源
    最近更新 更多