Competition problem in java web application

3

Good evening guys,

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 double-click the /[email protected] url in less than 5 seconds it will insert the email twice, which can not occur.

Ps: Thread.sleep () is only to illustrate the problem. In other places of my application I also call the emailDA.existeEmail () method.

How can I resolve this?

Thank you very much.

    
asked by anonymous 21.09.2014 / 02:26

1 answer

1

Your code contains some points, which deserve the following remarks:

  • Do not use thread operations in a container, unless you're going to manage the entire lifecycle of the Thread that you triggered yourself (eg ThreadPoolExecutor ), even more in this case that you have a Stateless bean, unpredictable results may occur regarding the competition. REF.

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

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

21.09.2014 / 17:02