Asynchronous Call Methods in EJB

I am trying to save the result of the login process for statistics in a database asynchronously in order to save time during the login method. But for some reason, the login process takes longer if I add thread.sleep to the async method. Why is this? I thought the authentication method would not wait for the writeResultToStats method to complete.

@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()); } } } 
+6
source share
2 answers

Try breaking the asynchronous method into a separate ejb. Methods called from the same ejb will be processed in the same way as local method calls. The container is not able to intercept the method call.

EJB Annotations are played only when playing when a call is made by the container.

Alternative

You can use the method in one EJB, but make sure you use the local EJB interface to find the bean and access the method.

+9
source

Take a look at this example - it shows that you do not need to create a separate EJB.

If you have a bean that has both synchronous and asynchronous methods, the asynchronous method cannot be called from the synchronous because the container will not intercept it.

But instead of creating another bean, you can call the asynchronous bean method via SessionContext:

 @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 } } 
+6
source

Source: https://habr.com/ru/post/945998/