Как подключить XAResource к существующей транзакции?

Мой вариант использования:

У меня есть существующий JTA TransactionManager и транзакция в полете. Я хотел бы подключить Neo4j в качестве XAResource к этой транзакции, чтобы он мог подготовить / зафиксировать в соответствующем 2PC.

Я не вижу публичной реализации XAResource в Neo4j; кажется, что все маршрутизируется через NioNeoDbPersistenceSource > NeoStoreXaDataSource > NeoStoreXaConnection.NeoStoreXaResource.

Есть ли предпочтительный способ зачисления Neo4j в транзакции JTA, помимо тех, которые предоставляются его собственным TransactionManager? Все тестовые наборы, которые я нахожу, подключают макет "FakeXAResource"[1]

Оценил!

S, ALR

[1] например, UseJOTMAsTxManagerIT

1 ответ

Хорошо, у меня есть решение, которое, я считаю, лучшее, с чем может справиться Neo4j, хотя я не в восторге от него.:)

https://gist.github.com/ALRubinger/b584065d0e7da251469a

Идея заключается в следующем:

1) Реализовать Neo4j AbstractTransactionManager

Этот неуклюжий класс представляет собой смесь JTA TransactionManager, Neo4j Lifecycle и некоторых других методов; мне не совсем ясно, для чего предназначены некоторые из них (например, "getEventIdentifier()" или "doRecovery()"), и в контракте указывается, что он переопределен. Я не уверен, почему нам нужны методы жизненного цикла для случая, когда Neo4j не является официальным владельцем TransactionManager.

2) Реализация Neo4j TransactionManagerProvider

Это позволит вам создать новый экземпляр вашей реализации AbstractTransactionManager, но он связан с SPI службы JDK, поэтому вы должны предоставить конструктор без аргументов и найти какой-то другой интеллектуальный / хакерский способ передачи контекстной информации.

3) Создайте файл META-INF/services/org.neo4j.kernel.impl.transaction.TransactionManagerProvider с содержимым полного доменного имени вашего TransactionManagerProvider из шага 2).

4) Когда вы создаете новый GraphDatabaseService, передайте в конфигурации, как:

final GraphDatabaseService graphDatabaseService = new GraphDatabaseFactory().
            newEmbeddedDatabaseBuilder(FILE_NAME_STORAGE).setConfig(
            GraphDatabaseSettings.tx_manager_impl.name(),
            "NAME_OF_YOUR_TXM_PROVIDER")
            .newGraphDatabase();

Затем вы получаете доступ к TransactionManager с использованием устаревшего API (GraphDatabaseAPI):

// Get at Neo4j's view of the TransactionManager
final TransactionManager tm = ((GraphDatabaseAPI)   graphDatabaseService).getDependencyResolver().resolveDependency(TransactionManager.class);
tm.begin();
final Transaction tx = tm.getTransaction();

Настоящая проблема, с которой я столкнулся при таком подходе, заключается в том, что мы должны использовать реализацию TransactionManager из Neo4j, которая упаковывает нашу настоящую TM. Что я хочу сделать, так это использовать мою TM и подключить Neo4j в качестве XAResource.

Так что я до сих пор не нашел способа сделать это, и, судя по комплектам тестов Neo4j, я не думаю, что это возможно в настоящий момент с какой-либо из предоставленных ими поддержки XAResource.

Абсолютно желающий и надеющийся быть исправленным!:)

Но, несмотря на то, что я упомянул выше, присоединенная сущность работает и показывает Neo4j, использующий внешний TransactionManager (Narayana, от нас в JBoss) в качестве вспомогательной реализации.

S, ALR

Другие вопросы по тегам