I try to save the result of a login process for statistics to the database asynchronously to save time during the login method. But somehow the login process takes longer if i add a thread.sleep to the async method. Why is that? I thought the authenticate method will not wait for the writeResultToStats methode to finish.
@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());
}
}
}
Try to break out the asynchronous method into a separate ejb. Methods invoked from inside the same ejb will be handled just like local method-invocations. The container is not capable of intercept the method call.
EJB-Annotations is only in play when invocation is done by the container.
You can have the method in the same EJB but make sure you use the EJB Local interface to lookup the bean and access the methord.
Take a look at this example - it shows that You do not need to create separate EJB.
If you have a bean which has both synchronous and asynchronous methods, the asynchronous method cannot be called from within the synchronous one because the container will not intercept it.
But instead of creating another bean, you can call the asynchronous bean method through the 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
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With