Concurrency problem in java web application

Question:

Good night people,

See the following code:

controller

@WebServlet("/testConcurrency")
public class TestConcurrency extends HttpServlet {
    private static final long serialVersionUID = -6124392524678396101L;

    @EJB(name="bs/UsuarioBS/local")
    private UsuarioBSLocal usuarioBS;

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String emailStr = request.getParameter("email");

        System.out.println("[Inicio] usuarioBS.testConcurrency();");

        try {
            usuarioBS.testConcurrency(emailStr);
        } catch (BusinessException e) {
            e.printStackTrace();
        }

        System.out.println("[Fim] usuarioBS.testConcurrency();");
    }
}

BS

@Stateless(name="business/UsuarioBS")
public class UsuarioBS implements UsuarioBSLocal {
    private Logger log = Logger.getLogger(UsuarioBS.class);

    @EJB(name="dao/EmailDAO/local")
    private EmailDAOLocal emailDAO;

    @Override
    public void testConcurrency(String emailStr) throws BusinessException {
        try {
            boolean existeEmail = emailDAO.existeEmail(emailStr);

            System.out.println("Existe email ["+ emailStr +"]? " + existeEmail);

            if (!existeEmail) {
                Email email = new Email(emailStr);
                email.setPessoa(new Pessoa(1l));
                email.setTipoEmail(TipoEmail.PRINCIPAL);

                try {
                    System.out.println("Waiting...");
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                emailDAO.inserir(email);

                System.out.println("Email ["+ emailStr +"] inserido!");
            }
        } catch (DAOException e) {
            e.printStackTrace();
        }
    }
}

If I call the url /testConcurrent?email=email@server.com.br twice in less than 5 seconds it will insert the email twice, which cannot happen.

Ps: Thread.sleep() is just to illustrate the problem. Elsewhere in my application I also call the emailDAO.existeEmail() method.

How can I solve this?

Thank you very much.

Answer:

Your code contains a few points, which deserve the following remarks:

  • Do not use thread operations on a container, unless you are going to manage the entire Thread lifecycle that you have triggered yourself (eg ThreadPoolExecutor ), even more so in this case that you have a Stateless bean, unpredictable results regarding concurrency can occur . REF.

  • Assuming your Thread.sleep() was OK, note that if you call the second time in less than 5 seconds (as you mentioned) you will have already verified the existence of the email in the bank AND will not have inserted anything yet. On the second call, nothing will be recorded yet, as the first call will still be locked. This isn't competition, it's just the model you're using.

  • Even by removing Thread.sleep() you could still have transaction-level concurrency issues (here we're talking milliseconds). This point is important to define the expected behavior as the transaction will be 'committed' depending on the attribute type being used ( More details here ). So this step is important to determine JPA Locking issues.

Scroll to Top
AllEscort