7

我尝试将用于统计的登录过程的结果异步保存到数据库中,以节省登录方法期间的时间。但是,如果我将 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());
            }

        }

    }
4

2 回答 2

10

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

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

选择

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

于 2013-05-28T09:00:03.913 回答
7

看看这个例子 - 它表明您不需要创建单独的 EJB。

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

但是您可以通过 SessionContext 调用异步 bean 方法,而不是创建另一个 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
    }
}
于 2013-07-15T11:34:03.957 回答