I found that a new thread created in the servlet donot contain the servlet/CDI context. I created a HelloWorld servlet (given below) to experiment with this problem. In the below example, you'll see that I am running 'doIt()' function in a new Thread (FutureTask). But it returns NULL but when I call 'doIt()' method directly, BeanManager is not NULL.
/**
* Servlet implementation class HelloWorld
*/
@WebServlet("/HelloWorld")
public class HelloWorld extends HttpServlet {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(HelloWorld.class
.getName());
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter writer = response.getWriter();
writer.println("<html>");
writer.println("<head><title>Hello World Servlet</title></head>");
writer.println("<body>");
writer.println("<h1>Context injection into Thread Experiment</h1>");
try {
// 1. This is NOT working
new Thread(testTask).start();
testTask.get(5000, TimeUnit.SECONDS);
// 2. This is working
//doIt();
} catch (Exception e) {
e.printStackTrace();
}
writer.println("<body>");
writer.println("</html>");
writer.close();
}
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
doIt();
} catch (Exception e) {
e.printStackTrace();
}
}
};
FutureTask<Object> testTask = new FutureTask<Object>(runnable, null);
protected void doIt() throws Exception {
if(getBeanManager() == null) {
throw new Exception( "BEAN MANAGER IS NULL");
}
}
public static BeanManager getBeanManager() {
try {
InitialContext initialContext = new InitialContext();
return (BeanManager) initialContext.lookup("java:comp/BeanManager");
} catch (NamingException e) {
logger.info("Couldn't get BeanManager through JNDI");
return null;
}
}
}
I searched online but could not find a good reference than saying it is possible. It would be great, if anybody can help me or provide me with some good pointers to inject/pass context into the new thread.
If you are using EJB 3.1 and Java EE 6 or greater, the notation @Asynchronous
on a method makes it run in a separate thread and takes care of managing resources, etc.
If you need more control, as pointed out by Kalpesh Soni, this answer describes how to use ManagedExecutorService
, if you have Java EE 7 or greater.
Additionally, I'm not sure if you really need that getBeanManager()
static method - wouldn't just @EJB BeanManager beanManager;
(or @Inject
) suffice?