Question

I'm confused as to how JTA transaction scopes interact with servlet calls. Say I have the servlet below:

@WebServlet("/UpdateFooServlet")
public class UpdateFooServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

@Inject
private FooDAO fooDAO;

/**
 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
 *      response)
 */
protected void doPost(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException {
    Foo foo = fooDAO.findById(Integer.parseInt(request.getParameter("id")));
    foo.setName(request.getParameter("name"));  
            // Should the transaction flush/commit after this returns?
}
}

FooDAO is annotated as @Stateless and has an EntityManager injected using @PersistenceContext. findById just calls em.find and returns the matching Foo. When I post to the servlet, the update to the foo object isn't persisted to the database.

This is deployed on a JBoss AS7 server, using an in-memory H2 database. I can persist Foo objects to the database without issue, but updating is confusing. I can't explicitly flush the entity manager (I can't join the transaction even if I inject the EntityManager into the servlet). If I POST to the servlet twice I can see the update SQL in the console, but not if I call the servlet once.

Was it helpful?

Solution

The problem is that the transaction borders are defined on the EJB layer, not Servlet, meaning if you would do that in the EJB method, that would be committed to the DB after your EJB method returns. Also bear in mind, that the Foo instance in your servlet is not managed anymore, which means that its changes are not tracked anymore.

On the other side, it would be a bad practice to implement any DB operations/business logic in your servlet.

To make it shorter: make another method save(Fao fao) in your DAO service with the following code:

em.merge(fao);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top