|
Answer from IBM Lab about WAS Transaction Management and Hibernate :
Hibernate have found and used an unpublished, internal interface of WAS 5.0 that is not supported for external use in WAS 5.0 and not available in WAS 5.1. Hibernate claim to be unable to obtain the TransactionManager interface and that, as a result of their inability to do this, IBM are " deliberately making it difficult for their customers". On the contrary, IBM have deliberately made it easy for their customers, and indeed 3rd party persistence vendors such as Hibernate, to integrate with the application server's transaction manager in a manner that exceeds the requirements of J2EE. Hibernate have incorrectly interpreted the J2EE specifications and have chosen not to exploit the extended JTA capabilities offered by WebSphere. Specifically, Hibernate desire the ability to be notified of transaction completion and have tried to exploit the WebSphere implementation of the JTA TransactionManager interace [1] to achieve this. This interface is not intended to be exposed by J2EE servers for application use - it defines the internal contract between the container and the transaction service. Because this is not part of the application programming model, J2EE defines no portable means for an application to access this interface - the precise means are internal to the application server. The only JTA API exposed by the J2EE architecture to applications is the UserTransaction API, to which Hibernate have full and supported access. [2] WebSphere recognises the value, to applications, of some function that could be acessed through the JTA TransactionManager interface and provides a supported, documented API (ExtendedJTATransaction) to access such function. This goes beyond the J2EE requirements on an application server and is an architected extension point to WebSphere's JTA support that a persistence manage such as Hibernate can exploit. It gives access to the transaction id and a means to register callback objects for notification of transaction completion, without exposing context manipulation interfaces that must remain under the exclusive control of the application server. This extension to JTA has been available since WAS Enterprise 5.0; it is also available in WBI-SF 5.1 and base WAS 6.0. [1] JTA Specification, 1.0.1b, http://java.sun.com/products/jta/ - section 3.2 [2] J2EE 1.3 Specification, section J2EE.6.8 Java™ Transaction API (JTA) 1.0 Requirements: "JTA defines the UserTransaction interface that is used by applications to start, and commit or abort transactions. Enterprise beans are expected to get UserTransaction objects through the EJBContext's getUserTransaction method. Other application components get a UserTransaction object through a JNDI lookup using the name java:comp/UserTransaction. JTA also defines a number of interfaces that are used by an application server to communicate with a transaction manager, and for a transaction manager to interact with a resource manager. These interfaces must be supported as described in the Connector specification." Just a shame that to do this we will get dependent on a IBM specific API (ExtendedJTATransaction and their Synchronization) instead of something that works anywhere else with a J2EE API (TransactionManager and Synchronization).
Any way that we can build such a thing without being compile/runtime dependent on a WebSphere jar we can't bundle ? We could use reflection.
yeah - and some cglib tricks to provide an implementation of the interface and expose their ExtendedJTATransaction as an TransactionManager or something...yucky!
btw. googling on ExtendedJTATransaction provides 3(three!) hits - not something I would call widely used nor documented ....but hey, it's there so i'll stop complaining ;)
I love this: IBM are "making things easy for their customers" by inventing WebSphere-specific interfaces to do things that /every other application server vendor/ does using standard interfaces defined by the JTA spec.
Well, at least we know what to do now. http://publib.boulder.ibm.com/infocenter/ws51help/index.jsp?topic=/com.ibm.wasee.doc/info/ee/javadoc/ee/com/ibm/websphere/jtaextensions/ExtendedJTATransaction.html CVS COMMIT LOG:
SUBJECT: [Hibernate-commits] Hibernate3/src/org/hibernate/transaction WebSphereExtendedJTATransactionLookup.java,1.1,1.2 HB-1354 support for crappy WebSphere proprietary vendor lock-in interfaces Please try out WebSphereExtendedJTATransactionLookup, and tell me if it works (or fix it if it doesn't). Thanks!
(In CVS, both branches.) CVS COMMIT LOG:
SUBJECT: [Hibernate-commits] Hibernate2/src/net/sf/hibernate/transaction WebSphereExtendedJTATransactionLookup.java,NONE,1.1 HB-1354 support for crappy WebSphere proprietary vendor lock-in interfaces CVS COMMIT LOG:
SUBJECT: [Hibernate-commits] Hibernate3/src/org/hibernate/transaction WebSphereExtendedJTATransactionLookup.java,NONE,1.1 HB-1354 support for crappy WebSphere proprietary vendor lock-in interfaces I've tested this integration with Websphere 6.0 and noticed the following issues:
##### 1. If you try to session.beginTransaction() when hibernate.transaction.factory_class is set to org.hibernate.transaction.JTATransactionFactory a NamingException occurs when getUserTransactionName method returns "java:comp/UserTransaction", as the user transaction is not available in WAS 6.0 CMT implementation. ##### 2. If you try to session.beginTransaction() When hibernate.transaction.factory_class is set to org.hibernate.transaction.JTATransactionFactory a ClassCastException occurs when WebSphereExtendedJTATransactionLookup is updated so that the getUserTransactionName method returns "java:comp/websphere/ExtendedJTATransaction". Class cast exception occurs in the JTATransaction begin(...) method when the lookup is cast to a UserTransaction. ##### 3. When not trying to begin a hibernate transaction, and if the hibernate.transaction.factory_class is not set, an Exception occurs in the SessionImpl isJTATransactionInProgress when the WebSphereExtendedJTATransactionLookup..TransactionAdapter getStatus method is called as this method is currently throwing an UnsupportedOperationException. ##### 4. Hard-coding the WebSphereExtendedJTATransactionLookup..TransactionAdapter getStatus method to return 0, (just to test what happens) will result in errors in the ExtendedJTATransaction. Specifically, a WAS 6.0 error is seen: registerSynchronizationCallback Entry <malformed parameter> error is visible in the logs. I've done some further research. The ExtendedJTA... API for WAS 6.0 contains different methods than that of 5.1. I've developed what I believe are the appropriate fixes and would be happy to provide them. To whom should I provide this information.
add it to this jira issue (or create a new one with more specific topic/version)
Changes are documented and included in upload.
2 Areas I'm not totally sure about, which maybe you guys have some better ideas: 1. The getStatus change in the WebSphereExtendedJTATransactionLookup. I've had to hard-code a valid return code as this method is called by the SessionImpl isJTATransactionInProgress method and will raise an exception if left in its current state. 2. The session close, can not be done by a DAO otherwise the beforeCompletion and afterCompletion methods will not have an open session to process. I've moved the close logic to the afterCompletion method (as you'll see) but perhaps there is a better way to handle this. I found this in one of the websphere help sites.
Does it have any relevance to this issue? "Earlier versions of WebSphere Application Server, up to and including 3.5.x (without EJB 1.1), bind the UserTransaction interface to a JNDI location of jta/usertransaction. WebSphere Application Server Version 4, and later releases, bind the UserTransaction interface at the location defined by EJB 1.1, which is java:comp/UserTransaction. WebSphere Application Server, Version 5 no longer provides the jta/usertransaction binding within Web and EJB containers to applications at a J2EE level of 1.3 or later." Additionally: "A web component or enterprise bean (CMT or BMT) can get the ExtendedJTATransaction interface through a lookup of java:comp/websphere/ExtendedJTATransaction. This interface provides access to the transaction identity and a mechanism to receive notification of transaction completion." We are using the new WebSphereExtendedJTATransactionLookup class to use our code in WAS with JTATransactionFactory. We wrote a small application to test this new class. But we always face with a ClassNotFoundException for "com.ibm.websphere.jtaextensions.SynchronizationCallback" when we call configuration.buildSessionFactory() method of our daofactory class. We tried to see that if we could call and get this class before and after (even after getting the exception, in catch block) the call. We saw that there is no problem with the class.forname call to "com.ibm.websphere.jtaextensions.SynchronizationCallback" class. But when hibernate tries to call the same class it gets the ClassNotFoundException.
try { System.out.println("1." + Class.forName("com.ibm.websphere.jtaextensions.SynchronizationCallback").toString()); sessionFactory = configuration.buildSessionFactory(); System.out.println("2." + Class.forName("com.ibm.websphere.jtaextensions.SynchronizationCallback").toString()); } catch (Exception exc) { System.out.println("3." + Class.forName("com.ibm.websphere.jtaextensions.SynchronizationCallback").toString()); System.out.println(exc.toString()); } sysout is: SystemOut O 1.interface com.ibm.websphere.jtaextensions.SynchronizationCallback SystemOut O 3.interface com.ibm.websphere.jtaextensions.SynchronizationCallback SystemOut O net.sf.hibernate.HibernateException: java.lang.ClassNotFoundException: We verified the class path by means of WAS V5 ClassLoader Viewer and saw the class. What could be the problem... I'm using Hibernate 2.1.8.
On WebSphere Portal Server 5.1, based on WebSphere Application Server 5.1 the JNDI lookup for jta/usertransaction throws an exception. "A Reference object looked up from the context "localhost/nodes/localhost/servers/WebSphere_Portal" with the name "jta/usertransaction" was sent to the JNDI Naming Manager and an exception resulted." I've checked the JNDI tree with the UTC and found that there is no such JNDI path as "localhost/nodes/localhost/servers/WebSphere_Portal" but "thisNode/servers/WebSphere_Portal/". I found no way of setting the initial context's base lookup path. (probably my fault) However specifing jta.UserTransaction as "thisNode/servers/WebSphere_Portal/jta/usertransaction" in the configuration file works fine. Just some quick questions. I've noticed that Gavin changed the status of this item in the log, but, I don't see that status reflected in the summary.
Also, is there any intention of investigating this further prior to the Hibernate 3 production release? yes it is planned to be solved before 3 final
The other piece is actually finishing out the JCA stuff, which I am currently working on. It's coded to JCA 1.5.
This will allow Hibernate to interact with TransactionManagers from any appserver (even crappy ones which hide the TM from public) in a standard way. This rewrite is actually pretty close to done. I am in the process of testing this with JBoss. I don't have access to websphere to be able to test on that environment. Testers for deployment of this RA onto websphere would be welcome. For those wanting to play with the new JCA stuff, please note that it is no longer in the main Hibernate3 CVS module. Instead it has been moved to its own seperate module (currently named container) to avoid dependency on JDK1.4, since it complies with the JCA1.5 spec.
The module builds by itself, although it needs hibernate3.jar and the required Hibernate dependencies. OK, I chatted to Edwin today, and he explained his patch to me, and I applied it, this should now work in WAS 6. The remaining task is to add a CMTTransaction implementation.
I am discovering this issue anew on WebSphere 6.0.2.9 and Hibernate 3.2.CR2, cf. <http://forum.hibernate.org/viewtopic.php?t=963579>.
Yea, I also was seeing something similar with H 3.2 CR4 and WS 6.
Using the comment above by Gergely Papp [17/Feb/05 03:59 AM], I added a cfg property for jndi namespace and all works well. So the following should solve the problem: <property name="connection.datasource">[your websphere datasource name]</property> <property name="dialect">org.hibernate.dialect.OracleDialect</property> <property name="transaction.manager_lookup_class">org.hibernate.transaction.WebSphereExtendedJTATransactionLookup</property> <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property> <property name="jta.UserTransaction">thisNode/servers/WebSphere_Portal/jta/usertransaction</property> Does the status closed mean the CMT is supported on WAS6 ?
I am facing an issue on using WebsphereExtendedJTATransactionLookup with Hibernate,JbossCache and on WAS6.0. The link to the forum where the issue is posted is as follows. http://forum.hibernate.org/viewtopic.php?t=968608 Briefly, I get an UnsupportedOperationException when introducing Jbosscache with Hibernate on WAS with CMT. If I use WebsphereTransactionmanagerLookup class instead, the exception is not seen. I do not if it is safe to use WebsphereTransactionManagerLookup meant for WAS5.1 on WAS6.0. Someone please clarify. I have tried the JTA jndi's mentioned in the previous comments, but it did not help. I do not know the internals of JTA too well to be able to contribute a patch or so that is required. Kindly give some feedback on the problem seen. |
||||||||||||||||||||||||||||||||||||||||||||||||||
IBM are completely out of step with the marketplace on this, and are deliberately making it difficult for their customers.