В настоящее время мне нужно манипулировать некоторым кодом c EclipseLink из самой библиотеки EclipseLink. Столкнулся с неприятной проблемой, когда мне нужно увеличить уровень трассировки на уровне параллелизма EclipseLink.
Один фрагмент метаданных, который я хочу получить для моей трассировки, - это идентификатор текущей транзакции JTA.
Поскольку мои изменения кода происходят в середине диспетчера параллелизма EclipseLink, я на самом деле очень ограничен в плане активного контекста выполнения. Мне доступно очень мало контекста, определенно, в тот момент, когда я добавляю трассировку, в моих руках нет диспетчера сущностей.
К счастью, в приложениях JEE у вас есть мощный уровень JNDI для доступа в любой момент на момент времени.
Вопрос прост: существует ли какое-либо официальное имя поиска JEE JNDI, которое официально допустимо для получения идентификатора текущей транзакции JTA?
В приложении Java EE, если вы внутри для вставляемого контекста CDI вы можете сделать что-то вроде:
@Resource
transient TransactionSynchronizationRegistry tsr;
И оттуда вы получите этот неприятный метод: tsr.getTransactionKey ()
Но объект, который выходит из него обычно имеет TO_STRING, который изменяется в зависимости от статуса транзакции.
Вот пример oracle.
Name = [EJB фасад.systemtest.ReproduceBugFacadeImpl.reproduceBugThreadThatReadsEntityD ()], Xid = BEA1-035D63C7D4B318977989 (1127385808), Статус = Откат. [Reason = weblogi c .transaction.internal.TimedOutException: время ожидания транзакции истекло через 61 секунду BEA1-035D63C7D4B318977989], numRepliesOwedMe = 0, numRepliesOwedOthers = 0, секунды с момента begin = 2311, activeSecread = -2180, использовать = Поток [[STUCK] ExecuteThread: '12' для очереди: 'weblogi c .kernel.Default (самонастройка)', 1, объединенные потоки], XAServerResourceInfo [DS_Maint-3568-eclipsedeadlock_oracledb] = (ServerResourceInfo [DS_Maint- 3568-eclipsedeadlock_oracledb] = (состояние = откат, назначено = AdminServer), xar = DS, повторно зарегистрировано = false), SCInfo [Maint-3568-eclipsedeadlock_oracledb + AdminServer] = (состояние = откат), свойства = ({weblogi c .transaction.partitionName = ДОМЕН, веб-журналы c .transaction.name = [EJB фасад.systemtest.ReproduceBugFacadeImpl.reproduceBugThreadThatReadsEntityD ()]}), локальные свойства = ({веб-журналы c .jdta c .jdta = [XAConnection не привязан к этому TxInfo]}), OwnerTransactionManager = ServerTM [ServerCoordinatorDescriptor = (CoordinatorURL = AdminServer + 10.41.144.234: 70 01 + Мейнт-3568-eclipsedeadlock_oracledb + T3 + CoordinatorNonSecureURL = AdminServer + 10.41.144.234: 7001Maint-3568-eclipsedeadlock_oracledb + T3 + coordinatorSecureURL = AdminServer + 10.41.144.234: 7002 + Мейнт-3568-eclipsedeadlock_oracledb + T3S + XAResources = {WLStore_Maint-3568-eclipsedeadlock_oracledb__WLS_AdminServer , DS_Maint-3568-eclipsedeadlock_oracledb, WSATGatewayRM_AdminServer_Maint-3568-eclipsedeadlock_oracledb}, NonXAResources = {})], CoordinatorURL = AdminServer + 10.41.144.234: 7001 + Maintsedeadlock * + 10.41.144.234: 7001 + Maintse-23 * tdlock
tclip-1021 * tclip *1022* tclip * + 1021 * tcl_3 * 8 * tcl_23 * + 1 * tcl_23 * + * tcl_23 * + * tcl_23 * + * tcl_23 * + * tcl_23 * + * tcl_23 * + 1 моя точка останова отладки, чтобы получить идентификатор транзакции, который мне нужен: (извините, что код выглядит так отвратительно, но eclipse не допускает выражения строки muti)
(( (new javax.naming.InitialContext()).lookup("java:comp/TransactionSynchronizationRegistry")).getClass().getMethod("getTransactionKey")).invoke(( (new javax.naming.InitialContext()).lookup("java:comp/TransactionSynchronizationRegistry"))).getClass().getMethod("getXid").invoke( (( (new javax.naming.InitialContext()).lookup("java:comp/TransactionSynchronizationRegistry")).getClass().getMethod("getTransactionKey")).invoke( (new javax.naming.InitialContext()).lookup("java:comp/TransactionSynchronizationRegistry")) )
И это дает мне именно то, что я хочу:
BEA1-035D63C7D4B318977989
Нет лучшего способа java some basi c JNDI до тех пор, пока не появится вспомогательный класс, который придет с идентификатором транзакции должным образом независимо ?
Для меня эта информация абсолютно критично ... Тип отслеживания, который я добавляю к уровню параллелизма EclipseLink, должен точно знать, в какой транзакции JPA был выпущен или сброшен определенный ключ кеша c. Без этого я не могу определить конкретную ошибку.
Следующее - то же самое, что и приведенные выше однострочные выражения, но их легче читать. Должен быть способ сделать это лучше:
/**
* Reflection method for {@code javax.transaction.TransactionSynchronizationRegistry.getTransactionKey()}
*
* The transaction object key in weblogic has a to string of the form
* {@code Name=[EJB facade.systemtest.ReproduceBugFacadeImpl.reproduceBugThreadThatReadsEntityD()],Xid=BEA1-035D63C7D4B318977989(1127385808),Status=Rolled back. [Reason=weblogic.transaction.internal.TimedOutException: Transaction timed out after 61 seconds
* BEA1-035D63C7D4B318977989],numRepliesOwedMe=0,numRepliesOwedOthers=0,seconds since begin=1230,seconds
* left=-1099,useSecure=false,activeThread=Thread[[STUCK] ExecuteThread: '12' for queue: 'weblogic.kernel.Default
* (self-tuning)',1,Pooled
* Threads],XAServerResourceInfo[_DS_Maint-3568-eclipsedeadlock_oracledb]=(ServerResourceInfo[_DS_Maint-3568-eclipsedeadlock_oracledb]=(state=rolledback,assigned=AdminServer),xar=_DS,re-Registered
* =
* false),SCInfo[Maint-3568-eclipsedeadlock_oracledb+AdminServer]=(state=rolledback),properties=({weblogic.transaction.partitionName=DOMAIN,
* weblogic.transaction.name=[EJB
* facade.systemtest.ReproduceBugFacadeImpl.reproduceBugThreadThatReadsEntityD()]}),local
* properties=({weblogic.jdbc.jta._DS=[ No XAConnection is attached to this TxInfo
* ]}),OwnerTransactionManager=ServerTM[ServerCoordinatorDescriptor=(CoordinatorURL=AdminServer+10.41.144.234:7001+Maint-3568-eclipsedeadlock_oracledb+t3+
* CoordinatorNonSecureURL=AdminServer+10.41.144.234:7001+Maint-3568-eclipsedeadlock_oracledb+t3+
* coordinatorSecureURL=AdminServer+10.41.144.234:7002+Maint-3568-eclipsedeadlock_oracledb+t3s+,
* XAResources={WLStore_Maint-3568-eclipsedeadlock_oracledb__WLS_AdminServer,
* _DS_Maint-3568-eclipsedeadlock_oracledb,
* WSATGatewayRM_AdminServer_Maint-3568-eclipsedeadlock_oracledb},NonXAResources={})],CoordinatorURL=AdminServer+10.41.144.234:7001+Maint-3568-eclipsedeadlock_oracledb+t3+)
* }
*/
private static Method TRANSACTION_SYNCH_REGISTRY_TRANSACT_KEY_METHOD = null;
/**
* Reflection method for {@code javax.transaction.TransactionSynchronizationRegistry.getTransactionKey().getXid()}
*
* Which is a method that returns a transaction id of the from: {@code BEA1-035D63C7D4B318977989}
*/
private static Method WEBGLOCIC_TRANSACTION_XID_METHOD = null;
/**
*
* @return A DTo that can tells us the app server transaction ID on which eclipselink is currently working. This is
* additional metadata we can add when we are acquiring for example a read lock.
*/
public HackingEclipseCurrentJtaTransactionInfoDto createHackingEclipseCurrentJtaTransactionInfoDto() {
try {
InitialContext jndi = new InitialContext();
// (a) Load the method methodGetTransactionKey getTransactionKey
Method methodGetTransactionKey = getTransactionSynchronizationRegistryGetTransactionKeyMethod();
// (b) load the javax.transaction.TransactionSynchronizationRegistry
Object transactionSynchronizationRegistry = jndi.lookup("java:comp/TransactionSynchronizationRegistry");
// (c) execute the getTransactionKey on the TransactionSynchronizationRegistry
Object transactionSynchronizationRegistryTransactionKey = methodGetTransactionKey
.invoke(transactionSynchronizationRegistry);
// (d) Get the method to get the weblogic transaction ids
// currently we only support weblogic
Method weblogicGetXid = getWeblogicBEATransactionId(transactionSynchronizationRegistryTransactionKey);
Object jpaTranasctionId = "actualTransactionIdNotSupportedForCurrentAppServer";
if (weblogicGetXid != null) {
jpaTranasctionId = weblogicGetXid.invoke(transactionSynchronizationRegistryTransactionKey);
}
// (e) If we reached this point we can now bbuild our DTO with the to strings from the two objects we care
// abou
return new HackingEclipseCurrentJtaTransactionInfoDto(
transactionSynchronizationRegistryTransactionKey.toString(), jpaTranasctionId.toString());
} catch (Exception e) {
final String dummyId = "createHackingEclipseCurrentJtaTransactionInfoDto_problems_doing_jndi_lookup";
return new HackingEclipseCurrentJtaTransactionInfoDto(dummyId, dummyId);
}
}
/**
* @return the cached reflection method to get the Method
* {@code javax.transaction.TransactionSynchronizationRegistry.getTransactionKey()}
*/
public static synchronized Method getTransactionSynchronizationRegistryGetTransactionKeyMethod() {
try {
if (TRANSACTION_SYNCH_REGISTRY_TRANSACT_KEY_METHOD == null) {
InitialContext jndi = new InitialContext();
Object transactionSynchronizationRegistry = jndi.lookup("java:comp/TransactionSynchronizationRegistry");
TRANSACTION_SYNCH_REGISTRY_TRANSACT_KEY_METHOD = transactionSynchronizationRegistry.getClass()
.getMethod("getTransactionKey");
}
return TRANSACTION_SYNCH_REGISTRY_TRANSACT_KEY_METHOD;
} catch (Exception unexpectedError) {
throw new RuntimeException("getTransactionSynchronizationRegistryGetTransactionKeyMethod blew up",
unexpectedError);
}
}
/**
*
* @param transactionKeyObject
* this the java object that comes out of doing {@code javax.transaction.TransactionSynchronizationRegistry.getTransactionKey()}
* @return The weblogic transaction key object is an object that contains a metod getXid which we want to load
*/
public static synchronized Method getWeblogicBEATransactionId(Object transactionKeyObject) {
if (WEBGLOCIC_TRANSACTION_XID_METHOD == null) {
if (transactionKeyObject == null) {
return null;
}
// In weblogic the transaction key object is an instanc eof
// weblogic.transaction.internal.ServerTransactionImpl
boolean isAppServerWelogic = transactionKeyObject.getClass().getCanonicalName().contains("weblogic");
if (!isAppServerWelogic) {
return null;
}
// In weblogic the class weblogic.transaction.internal.ServerTransactionImpl
// has a very useful method getXid that returns BEA1-035D63C7D4B318977989
try {
WEBGLOCIC_TRANSACTION_XID_METHOD = transactionKeyObject.getClass().getMethod("getXid");
} catch (Exception unexpectedError) {
throw new RuntimeException("getWeblogicBEATransactionId blew up", unexpectedError);
}
}
return WEBGLOCIC_TRANSACTION_XID_METHOD;
}