【问题标题】:Call Methods Asynchronous in EJBEJB 中的异步调用方法
【发布时间】:2013-05-23 04:01:23
【问题描述】:

我尝试将用于统计的登录过程的结果异步保存到数据库中,以节省登录方法期间的时间。但是,如果我将 thread.sleep 添加到异步方法中,登录过程会以某种方式花费更长的时间。这是为什么?我认为身份验证方法不会等待 writeResultToStats 方法完成。

    @Stateless
    @LocalBean
    @ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
    @TransactionManagement(TransactionManagementType.CONTAINER)
    public class CustomerBeanTest {

        @PersistenceContext(unitName = WebPersistenceUnits.QISADS)
        private EntityManager em_local;

        @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
        public void authenticate(Long loginid, String cmppassword) {
            try {
                Login l = em_local.find(Login.class, loginid);
                String s = l.getPassword();
                if (!s.equalsIgnoreCase(cmppassword))
                    throw new PasswordMissmatchException();
                writeResultToStats(loginid, true);
            } catch (PasswordMissmatchException e) {
                writeResultToStats(loginid, false);
            }
        }

        @Asynchronous
        @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
        private void writeResultToStats(Long loginID, boolean success) {

            try { // just for testing
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            LogUtils log = new LogUtils(this);
            Login l = em_local.find(Login.class, loginID);
            if (success) {
                l.setSuccessLast(new Date());
                l.setSuccessCount(l.getSuccessCount()+1);
                log.log(Level.INFO, "Update Login Stat Success [%d, %s, %d]", l.getId(), l.getName(), Thread.currentThread().getId());
            } else {
                l.setFailureLast(new Date());
                l.setFailureCount(l.getFailureCount()+1);
                log.log(Level.INFO, "Update Login Stat Fail [%d, %s, %d]", l.getId(), l.getName(), Thread.currentThread().getId());
            }

        }

    }

【问题讨论】:

  • 我认为您需要将异步方法分解为另一个 ejb。就像现在一样,它只是作为本地方法调用处理
  • 让我试试这个然后回复你

标签: jakarta-ee asynchronous ejb-3.0 glassfish-3 ejb-3.1


【解决方案1】:

尝试将异步方法分解为单独的 ejb。从同一个 ejb 内部调用的方法将像本地方法调用一样被处理。容器无法拦截方法调用。

EJB-Annotations 仅在容器完成调用时起作用。

另类

您可以在同一个 EJB 中拥有该方法,但请确保您使用 EJB Local 接口来查找 bean 并访问该方法。

【讨论】:

    【解决方案2】:

    看看this 示例 - 它表明您不需要创建单独的 EJB。

    如果你有一个同时有同步和异步方法的bean,异步方法不能从同步方法中调用,因为容器不会拦截它。

    但是不用创建另一个bean,你可以通过SessionContext调用异步bean方法:

    @Stateless
    public class OrderProcessorBean {
        @Inject
        SessionContext ctx;
        //synchronous method invoked from EJB call outside this class
        public void synch() {
            //call asynch method
            ctx.getBusinessObject(OrderProcessorBean.class).asynch();
        }
    
        @Asynchronous
        public void asynch() {
             //asynch logic
        }
    }
    

    【讨论】:

    • 请注意,不鼓励仅链接的答案,因此答案应该是搜索解决方案的终点(相对于另一个参考中途停留,随着时间的推移往往会变得陈旧)。请考虑在此处添加独立的概要,并保留链接作为参考。
    猜你喜欢
    • 2015-03-01
    • 1970-01-01
    • 2015-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多