Когда следует вызывать Transaction.delistResource ()? - PullRequest
2 голосов
/ 24 августа 2011

Мы используем кэши LRU в памяти для нескольких различных моделей в нашем приложении.Чтобы избежать проблем, возникающих при откате транзакций (например, устаревшие записи), было добавлено понятие транзакционных кешей: для каждой транзакции создается временный кеш, а затем записи отбрасываются, если откат выполняется или они копируются в основную.кеш для этой модели, если она зафиксирована.

Для этого кеш реализует XAResource и переопределяет методы commit() и rollback().Всякий раз, когда новый Transaction хочет получить доступ к некоторым данным, которых нет в главном кэше, создается транзакционный кеш и передается в enlistResource().

. Проблема в том, что я пытался вызвать delistResource() накешировать экземпляр в методах commit() и rollback(), который выдавал IllegalStateException, сообщая, что транзакция уже помечена для отката (или принятия).Поэтому мне было интересно ... Это нормально, если не исключить кеш из списка как ресурс (другими словами, он уже исключен из списка как часть процесса отката или фиксации), или есть другая точка впоток где это должно называться?

1 Ответ

1 голос
/ 24 августа 2011

Это не методы XAResource, которые вызывают delistResource, а реализация транзакций сервера приложений. Если вы хотите, чтобы ресурс был удален из списка, получите транзакцию и вызовите ее, он при необходимости вызовет end () для ресурса. Менеджер транзакций также неявно вызывает end () как часть обработки завершения, поэтому вы не делаете это вручную при фиксации или откате. Единственный случай, когда вам нужно обработать список, - это использование одного и того же экземпляра ресурса в нескольких контекстах транзакции. Например


    Cache c = getCache();
    c.makeUpdate(); // no transaction running, should auto commit.
    tx.begin(); // start tx A
    c.makeUpdate(); // transactional within A
    tx.suspend();
    tx.begin(); // start tx B
    c.makeUpdate(); // transactional within B
    tx.commit(); //end B
    tx.resume(A);
    tx.commit(); // end A

В зависимости от реализации вашего кэша вам может потребоваться исключить из списка приостановку и снова подключиться при возобновлении, но не для фиксации или отката. В качестве альтернативы вы проверяете контекст транзакции при каждом вызове makeUpdate (), а не полагаетесь на последовательность вызовов enlist / delist, чтобы обновить эффективный контекст tx, хранящийся в экземпляре ресурса.

Эта штука сложная из-за плохого отображения между процедурной спецификацией XA и более или менее объектно-ориентированной спецификацией JTA. Честно говоря, вам, вероятно, лучше оставить это экспертам. Например, JBoss Infinispan предоставляет транзакционный кеш с открытым исходным кодом, который позаботится обо всем этом для вас, а также предлагает множество других функций.

...