code Java

30.08.2018


Переходя к примеру, хочется отметить, что среди всего многообразия возможных кейсов, наибольший интерес представляют задачи, выполняемые в распределенной среде JavaEE и в которых важно обеспечить поддержку транзакционности в многопоточной среде. Как известно, в JavaEE разработана спецификация JTA (Java Transaction API), которая позволяет определять границы транзакции, явно начиная её методом begin() и завершая методами commit(), фиксируя изменения, или rollback(), откатывающий произведенные действия.

Рассмотрим пример таска, который возвращает сообщение из некоторого списка, состоящего из ста элементов, по индексу в рамках пользовательской транзакции:

public class TransactionSupportCallableTask implements Callable<String> {

    private int messageIndex;

    public TransactionSupportCallableTask(int messageId) {
        this. messageIndex = messageId;
    }

    public String call() {
        UserTransaction tx = lookupUserTransaction();
        String message = null;
        try {
            tx.begin();
            message = getMessage(messageIndex);
            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
            try {
                tx.rollback();
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }
        return message;
    }

    private void getMessage(int index) {  }

    private UserTransaction lookupUserTransaction () {  }

}

Код сервлета, выводящего сообщение из списка по случайно выбранному индексу:

@WebServlet("/task")
public class ManagedExecutorServiceServlet extends HttpServlet {

    @Resource(lookup = "concurrent/OtusExecutorService")
    ManagedExecutorService executor;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Future<String> futureResult = executor.submit(new TransactionSupportCallableTask(Random.nextInt(100)));
        while (!futureResult.isDone()) {
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            response.getWriter().write("Callable task has received message with following content '" + futureResult.get() + "'");
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

Предыдущий кейс можно переписать следующим образом:

@WebServlet("/scheduledTask")
public class ManagedScheduledExecutorServiceServlet extends HttpServlet {

    @Resource(lookup = "concurrent/OtusScheduledExecutorService")
    ManagedScheduledExecutorService scheduledExecutor;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ScheduledFuture<String> futureResult = scheduledExecutor.schedule(
                new TransactionSupportCallableTask(Random.nextInt(100)), 5, TimeUnit.SECONDS);
        while (!futureResult.isDone()) {
            try {
                Thread.sleep(50); // Wait
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            response.getWriter().write("Callable task received message with following content '" + futureResult.get() + "'");
        } catch ( Exception e) {
            e.printStackTrace();
        }
    }
}

Поделиться: