早上好。 当我标记一个回滚事务时,我需要在JPA,Hibernate和WebSPhere 8之间修复一个“UnsuportedOperationException”。
我有这堂课:
package es.nspt.hiber.team.utils;
import java.lang.reflect.Method;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.InvalidTransactionException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.Status;
import javax.transaction.Synchronization;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;
import javax.transaction.xa.XAResource;
import org.hibernate.HibernateException;
import org.hibernate.service.jta.platform.internal.AbstractJtaPlatform;
public class WebSphereUOWTransactionLookup extends AbstractJtaPlatform {
private static final long serialVersionUID = 6514686920271789210L;
private static final String UOW_MANAGER_JNDI = "java:comp/websphere/UOWManager";
private static final String UOW_SYNCHRONIZATION_MANAGER_JNDI = "java:comp/websphere/UOWSynchronizationRegistry";
public static final String UT_NAME = "java:comp/UserTransaction";
@Override
protected TransactionManager locateTransactionManager() {
return new TransactionManagerAdapter();
}
@Override
protected UserTransaction locateUserTransaction() {
return (UserTransaction) jndiService().locate(UT_NAME);
}
public class TransactionManagerAdapter implements TransactionManager {
private final Class uowManagerClass;
private final Class uowSynchronizationRegistryClass;
private Object uowManager;
private Object uowSynchronizationRegistry;
private final Method registerSynchronizationMethod;
private final Method setRollbackOnlyMethod;
private final Method getLocalIdMethod;
@SuppressWarnings({ "unchecked", "rawtypes" })
private TransactionManagerAdapter() {
try {
uowManagerClass = Class.forName("com.ibm.wsspi.uow.UOWManager");
setRollbackOnlyMethod = uowManagerClass.getMethod("setRollbackOnly", new Class[] {});
uowSynchronizationRegistryClass = Class.forName("com.ibm.websphere.uow.UOWSynchronizationRegistry");
registerSynchronizationMethod = uowSynchronizationRegistryClass.getMethod("registerInterposedSynchronization", new Class[] { Synchronization.class });
Class extendedJTATransactionClass = Class.forName("com.ibm.websphere.jtaextensions.ExtendedJTATransaction");
getLocalIdMethod = extendedJTATransactionClass.getMethod("getLocalId", null);
} catch (ClassNotFoundException cnfe) {
throw new HibernateException(cnfe);
} catch (NoSuchMethodException nsme) {
throw new HibernateException(nsme);
}
}
/**
* Lazily loaded because UOW_MANAGER_JNDI isn't always available on
* Hibernate startup (when
* HibernatePersistence.createContainerEntityManagerFactory is called).
*/
private Object getUowManager() {
if (uowManager == null) {
uowManager = jndiService().locate(UOW_MANAGER_JNDI);
}
return uowManager;
}
private Object getUowSynchronizationRegistry() {
if (uowSynchronizationRegistry == null) {
uowSynchronizationRegistry = jndiService().locate(UOW_SYNCHRONIZATION_MANAGER_JNDI);
}
return uowSynchronizationRegistry;
}
public void begin() throws NotSupportedException, SystemException {
throw new UnsupportedOperationException();
}
public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException {
throw new UnsupportedOperationException();
}
@Override
public int getStatus() throws SystemException {
return getTransaction() == null ? Status.STATUS_NO_TRANSACTION : getTransaction().getStatus();
}
public Transaction getTransaction() throws SystemException {
return new TransactionAdapter();
}
public void resume(Transaction txn) throws InvalidTransactionException, IllegalStateException, SystemException {
throw new UnsupportedOperationException();
}
public void rollback() throws IllegalStateException, SecurityException, SystemException {
throw new UnsupportedOperationException();
}
public void setRollbackOnly() throws IllegalStateException, SystemException {
try {
setRollbackOnlyMethod.invoke(getUowManager(), new Object[] {});
} catch (Exception e) {
throw new HibernateException(e);
}
}
public void setTransactionTimeout(int i) throws SystemException {
throw new UnsupportedOperationException();
}
public Transaction suspend() throws SystemException {
throw new UnsupportedOperationException();
}
public class TransactionAdapter implements Transaction {
private final Object extendedJTATransaction;
private TransactionAdapter() {
extendedJTATransaction = jndiService().locate("java:comp/websphere/ExtendedJTATransaction");
}
public void registerSynchronization(final Synchronization synchronization) throws RollbackException, IllegalStateException, SystemException {
try {
registerSynchronizationMethod.invoke(getUowSynchronizationRegistry(), new Object[] { synchronization });
} catch (Exception e) {
throw new HibernateException(e);
}
}
public int hashCode() {
return getLocalId().hashCode();
}
public boolean equals(Object other) {
if (!(other instanceof TransactionAdapter))
return false;
TransactionAdapter that = (TransactionAdapter) other;
return getLocalId().equals(that.getLocalId());
}
private Object getLocalId() {
try {
return getLocalIdMethod.invoke(extendedJTATransaction, null);
} catch (Exception e) {
throw new HibernateException(e);
}
}
public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException {
throw new UnsupportedOperationException();
}
public boolean delistResource(XAResource resource, int i) throws IllegalStateException, SystemException {
throw new UnsupportedOperationException();
}
public boolean enlistResource(XAResource resource) throws RollbackException, IllegalStateException, SystemException {
throw new UnsupportedOperationException();
}
public int getStatus() throws SystemException {
return new Integer(0).equals(getLocalId()) ? Status.STATUS_NO_TRANSACTION : Status.STATUS_ACTIVE;
}
public void rollback() throws IllegalStateException, SystemException {
throw new UnsupportedOperationException();
}
public void setRollbackOnly() throws IllegalStateException, SystemException {
try {
setRollbackOnlyMethod.invoke(getUowManager(), new Object[] {});
} catch (Exception e) {
throw new HibernateException(e);
}
}
}
}
/**
* {@inheritDoc}
*/
public Object getTransactionIdentifier(Transaction transaction) {
// WebSphere, however, is not a sane JEE/JTA container…
return new Integer(transaction.hashCode());
}
}
但是当我的App启动一个事务时,我在日志中看到了这个错误:
Caused by: org.hibernate.service.jndi.JndiException: Unable to lookup JNDI name [java:comp/websphere/ExtendedJTATransaction]
at org.hibernate.service.jndi.internal.JndiServiceImpl.locate(JndiServiceImpl.java:68)
at
es.nspt.hiber.team.utils
.WebSphereUOWTransactionLookup$TransactionManagerAdapter$TransactionAdapter.<init>(WebSphereUOWTransactionLookup.java:133)
at
es.nspt.hiber.team
.utils.WebSphereUOWTransactionLookup$TransactionManagerAdapter$TransactionAdapter.<init>(WebSphereUOWTransactionLookup.java:128)
at
es.nspt.hiber.team.utils
.WebSphereUOWTransactionLookup$TransactionManagerAdapter.getTransaction(WebSphereUOWTransactionLookup.java:101)
at
es.nspt.hiber.team.utils
.WebSphereUOWTransactionLookup$TransactionManagerAdapter.getStatus(WebSphereUOWTransactionLookup.java:97)
at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.getStatus(JtaStatusHelper.java:73)
at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.isActive(JtaStatusHelper.java:115)
at org.hibernate.service.jta.platform.internal.TransactionManagerBasedSynchronizationStrategy.canRegisterSynchronization(TransactionManagerBasedSynchronizationStrategy.java:56)
at org.hibernate.service.jta.platform.internal.AbstractJtaPlatform.canRegisterSynchronization(AbstractJtaPlatform.java:148)
at org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl.attemptToRegisterJtaSync(TransactionCoordinatorImpl.java:247)
at org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl.pulse(TransactionCoordinatorImpl.java:284)
at org.hibernate.ejb.AbstractEntityManagerImpl.joinTransaction(AbstractEntityManagerImpl.java:1212)
at org.hibernate.ejb.AbstractEntityManagerImpl.postInit(AbstractEntityManagerImpl.java:178)
at org.hibernate.ejb.EntityManagerImpl.<init>(EntityManagerImpl.java:89)
at org.hibernate.ejb.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:193)
at org.hibernate.ejb.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:188)
at sun.reflect.GeneratedMethodAccessor16.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:613)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.invokeProxyMethod(AbstractEntityManagerFactoryBean.java:388)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean$ManagedEntityManagerFactoryInvocationHandler.invoke(AbstractEntityManagerFactoryBean.java:541)
at com.sun.proxy.$Proxy1788.createEntityManager(Unknown Source)
at org.springframework.orm.jpa.EntityManagerFactoryUtils.doGetTransactionalEntityManager(EntityManagerFactoryUtils.java:285)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:252)
at com.sun.proxy.$Proxy1791.merge(Unknown Source)
at org.springframework.integration.jpa.core.DefaultJpaOperations.persistOrMerge(DefaultJpaOperations.java:271)
at org.springframework.integration.jpa.core.DefaultJpaOperations.merge(DefaultJpaOperations.java:212)
at org.springframework.integration.jpa.core.JpaExecutor.executeOutboundJpaOperation(JpaExecutor.java:244)
at org.springframework.integration.jpa.outbound.JpaOutboundGateway.handleRequestMessage(JpaOutboundGateway.java:80)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:170)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
... 243 more
Caused by: javax.naming.ConfigurationException: A JNDI operation on a "java:" name cannot be completed because the server runtime is not able to associate the operation's thread with any J2EE application component. This condition can occur when the JNDI client using the "java:" name is not executed on the thread of a server application request. Make sure that a J2EE application does not execute JNDI operations on "java:" names within static code blocks or in threads created by that J2EE application. Such code does not necessarily run on the thread of a server application request and therefore is not supported by JNDI operations on "java:" names. [Root exception is javax.naming.NameNotFoundException: Name comp/websphere not found in context "java:".]
at com.ibm.ws.naming.java.javaURLContextImpl.throwExceptionIfDefaultJavaNS(javaURLContextImpl.java:522)
at com.ibm.ws.naming.java.javaURLContextImpl.throwConfigurationExceptionWithDefaultJavaNS(javaURLContextImpl.java:552)
at com.ibm.ws.naming.java.javaURLContextImpl.lookupExt(javaURLContextImpl.java:481)
at com.ibm.ws.naming.java.javaURLContextRoot.lookupExt(javaURLContextRoot.java:485)
at com.ibm.ws.naming.java.javaURLContextRoot.lookup(javaURLContextRoot.java:396)
at org.apache.aries.jndi.DelegateContext.lookup(DelegateContext.java:157)
at javax.naming.InitialContext.lookup(InitialContext.java:426)
at org.hibernate.service.jndi.internal.JndiServiceImpl.locate(JndiServiceImpl.java:65)
... 273 more
Caused by: javax.naming.NameNotFoundException: Name comp/websphere not found in context "java:".
at com.ibm.ws.naming.ipbase.NameSpace.getParentCtxInternal(NameSpace.java:1969)
at com.ibm.ws.naming.ipbase.NameSpace.retrieveBinding(NameSpace.java:1376)
at com.ibm.ws.naming.ipbase.NameSpace.lookupInternal(NameSpace.java:1219)
at com.ibm.ws.naming.ipbase.NameSpace.lookup(NameSpace.java:1141)
at com.ibm.ws.naming.urlbase.UrlContextImpl.lookupExt(UrlContextImpl.java:1436)
at com.ibm.ws.naming.java.javaURLContextImpl.lookupExt(javaURLContextImpl.java:477)
答案 0 :(得分:1)
异常清楚地表明系统是Unable to lookup JNDI name [java:comp/websphere/ExtendedJTATransaction]
。确保WebSphere Configuration中存在提到的JNDI条目。
答案 1 :(得分:0)
JNDi名称有时不可见,因为Websphere不会在与WebSphere服务器相同的Java上下文中运行应用程序。我可以在我的应用程序启动时看到JNDi名称,但在应用程序运行和运行时没有。
最后,我为我的问题实现了另一个解决方案,丢弃了这段代码。谢谢大家的回复。