I trying to use Asynchronous method in JavaEE 6. I created Following classes. However, the result of output log is synchronous. It's not correct.
Stateless Class
@javax.ejb.Stateless
public class MailManager implements Serializable{
@Asynchronous
public void send(List<String> toList, Mail mail, final SystemSetting systemSetting) throws MailException, UnsupportedEncodingException{
boolean isError = false;
for(InternetAddress addr :addressList){
MimeMessage msg = getMimeMessage(addr, mail, session);
Transport.send(msg);
log.info("Sent email to ["+addr+"].");
}
if(isError){
throw new MailException("Mail sending error occurred. Check error log.");
}
log.debug("Async finish.");
}
}
ManagedBean
@Named
@SessionScoped
public class MailController extends AbstractController{
@Inject @new(MailCreater.class)
private MailFactory mailCreater;
@Inject
private MailManager mailManager;
public void send(){
Mail mail = null;
mail = mailCreater.createFromTemplate(this, false,
mimeInfo, "template/testTemplate.txt","template/FOOTER1.body", map);
mailManager.send(list, mail, systemSetting);
log.debug("send() finish.");
}
}
log
INFO[Log4jLogger] - Sent email to [test1@test.co.jp].
INFO [Log4jLogger] - Sent email to [test2@test.co.jp].
.
.
.
DEBUG [Log4jLogger] - Async finish.
DEBUG [Log4jLogger] - send() finish.
Error Code when I change @Inject to @EJB
warning : javax.ejb.EJBException: javax.ejb.EJBException:
javax.ejb.CreateException: Could not create stateless EJB
at
com.sun.ejb.containers.StatelessSessionContainer._getContext(StatelessSessionContainer.java:454)
at com.sun.ejb.containers.BaseContainer.getContext(BaseContainer.java:2547)
at com.sun.ejb.containers.BaseContainer.preInvoke(BaseContainer.java:1899)
at com.sun.ejb.containers.EjbAsyncTask.call(EjbAsyncTask.java:99)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Caused by: javax.ejb.EJBException: javax.ejb.CreateException: Could not
create stateless EJB
at
com.sun.ejb.containers.StatelessSessionContainer$SessionContextFactory.create(StatelessSessionContainer.java:726)
at
com.sun.ejb.containers.util.pool.NonBlockingPool.getObject(NonBlockingPool.java:247)
at
com.sun.ejb.containers.StatelessSessionContainer._getContext(StatelessSessionContainer.java:449)
... 7 more
Caused by: javax.ejb.CreateException: Could not create stateless EJB
at
com.sun.ejb.containers.StatelessSessionContainer.createStatelessEJB(StatelessSessionContainer.java:534)
at
com.sun.ejb.containers.StatelessSessionContainer.access$000(StatelessSessionContainer.java:95)
at
com.sun.ejb.containers.StatelessSessionContainer$SessionContextFactory.create(StatelessSessionContainer.java:724)
... 9 more
Caused by: java.lang.NullPointerException
at java.util.concurrent.ConcurrentHashMap.hash(ConcurrentHashMap.java:333)
at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:988)
at
org.jboss.weld.manager.BeanManagerImpl.getBean(BeanManagerImpl.java:1076)
at org.jboss.weld.manager.BeanManagerImpl.getBean(BeanManagerImpl.java:148)
at
org.glassfish.weld.services.JCDIServiceImpl._createJCDIInjectionContext(JCDIServiceImpl.java:169)
at
org.glassfish.weld.services.JCDIServiceImpl.createJCDIInjectionContext(JCDIServiceImpl.java:146)
at
com.sun.ejb.containers.BaseContainer.createEjbInstanceAndContext(BaseContainer.java:1639)
at
com.sun.ejb.containers.StatelessSessionContainer.createStatelessEJB(StatelessSessionContainer.java:475)
... 11 more
Your code MailController.send() sample is missing how you are currently getting the reference to MailManager. I assume mailManager is the reference but the sample doesn't show how that reference is made so I am flying a little blind here in terms of telling you exactly what's wrong.
However, in general, what you need to do is inject the MailManager EJB into MailController with something like @EJB MailManager mailManager;
Also its looks like you are relying on your logs to tell you if things are really going async or not. This can be problematic due to timing. Also the log snippet you have included does not include the "Sent email to" message which it looks like MailManager.send()
should be emitting if all goes well.
-- Update --
@KensukeSato raised a good question which was, "Should I use @Inject
or @EJB
as both 'work' in his case?"
It basically comes down to the fact the as of JavaEE6 CDI beans and EJB beans provide different functionality and that EJB session beans ARE CDI beans but CDI beans are not EJB session beans. So if you simply want EJB services you can use @EJB
to inject your session bean into your CDI bean. However, if in addition to @EJB
services you want the bean to leverage CDI services then you should use @Inject
.
What does CDI give you that EJB alone does not?
So if you need any of that in addition to EJB functionality then you would use @Inject
, otherwise you can simply use @EJB
.