Competition problem in java web application

Asked

Viewed 220 times

3

Good evening, everyone,

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

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

How can I fix this?

Thank you very much.

1 answer

1

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

  • Do not use thread operations in a container, unless you are going to manage all of the Thread Lifecycle that you have fired yourself (eg: Threadpoolexecutor), even more so in this case that you have a Stateless bean, unforeseeable competition results may occur. REF.

  • Assuming that your Thread.sleep() was OK, note that if you call the second time in less than 5 seconds (as you quoted) you will have already checked the existence of the email in the bank and will not have entered anything yet. Soon on the second call, you will not have anything recorded, because the first call will still be stuck. That’s not competition, it’s just the model you’re wearing.

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

  • Thread.Sleep() was inserted only to illustrate the problem. Here I am using JDBC. I’ve read about transaction attributes, but honestly I didn’t understand it very well. How it would be implemented in practice based on this code?

Browser other questions tagged

You are not signed in. Login or sign up in order to post.