EJB, внедренный в задачу, возвращает UnsatisfiedResolutionException

Я только что установил Glassfish 4 и пытаюсь реализовать веб-приложение, которое включает в себя длительный поток, который постоянно вставляет объекты в БД, который запускается при вызове сервлета. Когда EJB, управляющий сущностью, внедряется в задачу, я получаю UnsatisfiedResolutionException: WELD-001308: Невозможно разрешить какие-либо bean-компоненты для ошибки Type:... в методе Instance.get().

EJB

@Stateless
public class MeasureEJB {

    @Resource
    ManagedExecutorService managedExecutorService;

    @Inject
    Instance<UpdatingTask> myTaskInstance;


    @PersistenceContext(unitName = "smarthomePU")
    private EntityManager em;

    public List<Measure> findMeasures() {
        Query query = em.createQuery("SELECT b FROM Measure b");
        return query.getResultList();
    }

    public Measure createMeasure (Measure _measure) {
        em.persist(_measure);
        return _measure;
    }

    public void executeBgThread() {
        UpdatingTask myTask = myTaskInstance.get(); <- Here I get the error
        this.managedExecutorService.submit(myTask);
    }
}

Сервлет

@WebServlet(description = "Servlet used to start the historizer", urlPatterns = { "/starthistorizer" })
public class StartHistorizer extends HttpServlet {

    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public StartHistorizer() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
     *      response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        measureEjb.executeBgThread();

        response.getWriter().append("Served at: ").append(request.getContextPath());
        request.getRequestDispatcher("/index.jsp").forward(request, response);
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
     *      response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}

и задача

Открытый класс @Stateless UpdatingTask реализует Runnable {

private static final String TAG = "smarthome";

@EJB
MeasureEJB measureEjb;

@Override
public void run() {
    // TODO Auto-generated method stub
    BufferedReader br = null;

    try {
        <Insert entities upon sensor messages>
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

}

и наконец ошибка

[2016-09-02T13:19:17.419+0000] [glassfish 4.1] [WARNING] [] [javax.enterprise.web] [tid: _ThreadID=29 _ThreadName=http-listener-1(5)] [timeMillis: 1472822357419] [levelValue: 900] [[
  StandardWrapperValve[com.storassa.javaee.smarthome.StartHistorizer]: Servlet.service() for servlet com.storassa.javaee.smarthome.StartHistorizer threw exception
javax.ejb.EJBException
    at com.sun.ejb.containers.EJBContainerTransactionManager.processSystemException(EJBContainerTransactionManager.java:752)
    at com.sun.ejb.containers.EJBContainerTransactionManager.completeNewTx(EJBContainerTransactionManager.java:702)
    at com.sun.ejb.containers.EJBContainerTransactionManager.postInvokeTx(EJBContainerTransactionManager.java:507)
    at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4566)
    at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2074)
    at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2044)
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:220)
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88)
    at com.sun.proxy.$Proxy244.executeBgThread(Unknown Source)
    at com.storassa.javaee.smarthome.__EJB31_Generated__MeasureEJB__Intf____Bean__.executeBgThread(Unknown Source)
    at com.storassa.javaee.smarthome.StartHistorizer.doGet(StartHistorizer.java:36)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:416)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:283)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:283)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:200)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:132)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:111)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:536)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001308: Unable to resolve any beans for Type: class com.storassa.javaee.smarthome.UpdatingTask; Qualifiers: [@javax.enterprise.inject.Default()]
    at org.jboss.weld.bean.builtin.InstanceImpl.get(InstanceImpl.java:101)
    at com.storassa.javaee.smarthome.MeasureEJB.executeBgThread(MeasureEJB.java:39)
    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:64)
    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.aroundInvoke(SystemInterceptorProxy.java:140)
    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.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:212)
    ... 34 more
]]

person sthor69    schedule 02.09.2016    source источник


Ответы (2)


Добавьте аннотацию @LocalBean к UpdatingTask

Ваш сеансовый компонент реализует интерфейс, что означает, что он доступен только с этим интерфейсом в cdi. С @LocalBean это также доступно с именем классов.

person k5_    schedule 02.09.2016

Обычно невозможно выполнять EJB в случайно созданных потоках. Это связано с тем, что они ожидают найти контекстную информацию, такую ​​как безопасность и управление транзакциями, связанную с текущим исполняемым потоком.

Кроме того, никогда не рекомендуется создавать неуправляемые потоки в корпоративном приложении, поскольку у вас нет возможности контролировать такое использование ресурсов.

Обойти это можно с помощью утилит параллелизма Java EE 7, которые предоставляют механизмы для получения должным образом подготовленных потоков из пула потоков, который вы настроили на своем сервере.

Подробнее об этом можно прочитать на странице Java EE 7: Использование параллелизма Утилиты в асинхронных сервлетах.

person Steve C    schedule 06.09.2016
comment
Спасибо за совет. Я новичок в этих темах, поэтому мне нужно немного больше изучить параллелизм в JavaEE. - person sthor69; 13.09.2016
comment
В конце концов я узнал, что ваш ответ был правильным, так как предыдущий только удалил ошибку, но данные не были сохранены в БД. Я следовал правильному способу управления потоками в JavaEE, как описано в ссылке, на которую вы ссылались, и теперь все работает. +1 - person sthor69; 19.09.2016