Hi Ian,
Thanks for the advice. In the meantime, I have got container-managed
transactions working using the XAResource. I'm not even sure if what I am
doing is right any more! It seems a bit belt-and-braces for what I want to
do (ensure I can reliably use newly assigned UUIDs without persisting
transient session changes until my whole unit of work is complete).
Here is an example I wrote - if anyone happens to see a glaring mistake or
problem, please let me know.
/*
* Dominique: "Before a transactional resource is handed out to
a client,
an
* application server will associate its global transaction
with the
* resource (i.e. invoke XAResource.start). The client will
invoke
* methods on the non-XA part of the resource and at the end of
the
* request, the application server will disassociate the
resource
* (i.e. invoke XAResource.end) before eventually committing or
* rolling back changes on all resources involved in the global
* transaction".
*/
Xid xid = new Xid()
{
public byte[] getBranchQualifier()
{
return new byte[0];
}
public int getFormatId()
{
return 0;
}
public byte[] getGlobalTransactionId()
{
return new byte[0];
}
};
try
{
//My custom getSession() method returns a Session -
cast to XASession.
xaSession = (XASession) getSession();
xaResource = xaSession.getXAResource();
xaResource.start(xid, XAResource.TMNOFLAGS);
boolean commitSuccessful = false;
/*
* Now we've marked the start of our transaction with
* xaResource.start(), we can add our nodes and
properties
*/
Node rootNode = xaSession.getRootNode();
Node someNode = rootNode.addNode("some_node");
someNode.setProperty("name", "some name");
xaSession.save(); // This will not persist the changes
as we're in
transaction scope.
Node anotherNode = someNode.addNode("another_node");
anotherNode.setProperty("date",
Calendar.getInstance(TimeZone.getTimeZone("GMT"), Locale.UK));
xaSession.save(); // Last save before commit
// Finally commit this transaction to persist the
changes made to
xaSession.
xaResource.end(xid, XAResource.TMSUCCESS);
xaResource.prepare(xid);
xaResource.commit(xid, false);
commitSuccessful = true;
}
catch (Exception e)
{
// Handle exceptions better than this!
}
finally
{
if (commitSuccessful == false)
{
logger.error("Commit unsuccessful");
if (xaResource != null)
{
try
{
xaResource.end(xid,
XAResource.TMFAIL);
}
catch (XAException e)
{
logger.error("Error ending
transaction: " + e.getMessage());
}
}
}
xaSession.logout(); // Finally release the session
(whether commit was
successful or not).
}
Ian Boston wrote:
>
> Unfortunately I dont have any experience of JOTM, so I dont know if it
> will work with Jackrabbit. I do know that Geronimo's JTA works. There
> was another one mentioned on the lists a while back. JOTM says is does
> support XA so *should* work with Jackrabbit... if you an hold of a
> functional transaction manager.
>
> There is a JMS example on the JOTM site that uses XA, (might help ?)
> Ian
>
> On 3 Aug 2009, at 11:50, Gadbury wrote:
>
>>
>> Thank you Ian for your response. I appreciate it. Unfortunately, I
>> am now a
>> bit lost, going around in circles and banging my head against a
>> brick wall
>> :)
>>
>> I am using Tomcat 6.0 + JOTM 2.1.4 (also, I am not using spring-
>> modules-jcr)
>> and I am able to get my UserTransaction via JNDI (it is casted from an
>> org.objectweb.jotm.Current object, which implements javax.transaction
>> TransactionManager and UserTransaction interfaces). I have also tried
>> casting the Current object to TransactionManager and calling
>> transactionManager.getTransaction(), but no Transaction is returned.
>>
>> I'm not sure what else to try. I thought Jackrabbit did support
>> user and
>> container-managed transactions...? There seems to be no easy way
>> for me to
>> retrieve a Transaction or TransactionManager object with the setup I
>> am
>> using (although most likely I am just being stupid!). I have had a
>> look at
>> the container-managed transactions part of the JCR 1.0 spec
>> (associating the
>> resource with a global transaction using the myXAResource.start(xid,
>> TMNOFLAGS) and myXAResource.end(xid, TMSUSPEND); ), but that seems a
>> bit
>> heavy-weight. By the way, what happened to the XIDHelper class?
>>
>> Is there anyone out there that uses Tomcat, JOTM and transactions?
>>
>>
>> Ian Boston wrote:
>>>
>>> I will have a go at answering, but no guarantees :)
>>> On 1 Aug 2009, at 11:56, Gadbury wrote:
>>>
>>>>
>>>> Hi Ian,
>>>>
>>>> Thank you for the pointers. Was I wrong to use UserTransaction?
>>>
>>> I think (but I could be completely wrong), UserTransaction is
>>> generally a wrapper for the TransactionManager so when you create a
>>> user transaction jndi will associate the user transaction with the
>>> TransactionManager, and then the UserTransaction will proxy the
>>> remaining calls through to the TransactionManager (at least thats the
>>> case with Geronimo)
>>>
>>> You need to bind the JCR session into the transaction, which cant be
>>> done with a UserTransaction where the wiring is within the
>>> TransactionManager impl, usually bound to the JDBC data source. So
>>> your right to use UserTransaction for JDBC/Datasource, but wrong to
>>> use it for JCR. (IIRC)
>>>
>>>> What type
>>>> of tranasction is that in your example It looks to me like you're
>>>> using
>>>> Transaction and TransactionManager interfaces from
>>>> javax.transaction.
>>>
>>> yes
>>>
>>>> How
>>>> do I get a TransactionManager instance? Can I still use JNDI or is
>>>> there an
>>>> alternative (in fact, JNDI presents me a problem with unit testing
>>>> as
>>>> without the web application running on the Tomcat server, the JNDI
>>>> lookup
>>>> cannot get the UserTransaction instance) ?
>>>
>>> you *should* be able to look up the transaction manager from jNDI
>>> *or*
>>> for unit testing, create a new instance of the TransactionManager. I
>>> have been using Geronimo in OSGi with Sling/Jackrabbit and its just a
>>> new GeronimoTransactionManager(defaultTransactionTimeoutSeconds); to
>>> get one (only one per transaction context)
>>>
>>>>
>>>> Sorry for the silly questions. Thanks for your time. Regards,
>>>>
>>>> James
>>>>
>>>>
>>>> Ian Boston wrote:
>>>>>
>>>>> IIRC you have to bind the jcr session to the transaction. In
>>>>> Jackrabbit the session is actually an XASession with a
>>>>> getXAResource()
>>>>> method so you can bind the session with something like this.
>>>>>
>>>>> Transaction transaction = transactionManager.getTransaction();
>>>>> if (transaction != null) {
>>>>>
>>>>> transaction.enlistResource(((XASession)session).getXAResource());
>>>>> }
>>>>>
>>>>>
>>>>> HTH
>>>>> Ian
>>>>>
>>>>> On 31 Jul 2009, at 17:26, Gadbury wrote:
>>>>>
>>>>>>
>>>>>> Hi all,
>>>>>>
>>>>>> I have finally managed to get somewhere with jotm and Tomcat 6.0
>>>>>> having
>>>>>> followed the tutorial provided in the above links. I am finally
>>>>>> getting the
>>>>>> UserTransaction via JNDI lookup (after classloader issues and
>>>>>> naming
>>>>>> exceptions) and I am testing that new
>>>>>> InitialContext().lookup("java:comp/UserTransaction"); is an
>>>>>> instance
>>>>>> of
>>>>>> UserTranasction.
>>>>>>
>>>>>> Unfortunately, every session.save() called in between the
>>>>>> utx.begin() and
>>>>>> utx.commit() persists changes so the UserTranasction is not having
>>>>>> an
>>>>>> effect. I was hoping that session.save() would not persist
>>>>>> changes
>>>>>> in the
>>>>>> scope of a UserTranasction but would ensure that node UUIDs are
>>>>>> permanently
>>>>>> assigned to new nodes. For example:
>>>>>>
>>>>>> Session session = getSession();
>>>>>>
>>>>>> // Get user transaction (for example, through JNDI)
>>>>>> UserTransaction utx = (UserTransaction) new
>>>>>> InitialContext().lookup("java:comp/UserTransaction");
>>>>>>
>>>>>> JcrUserDao userDao = new JcrUserDao();
>>>>>> JcrProductDao productDao = new JcrProductDao();
>>>>>>
>>>>>> utx.begin();
>>>>>>
>>>>>> Node newUserNode = userDao.create(aUser, session);
>>>>>>
>>>>>> session.save();
>>>>>>
>>>>>> String UUID = newUserNode.getUUID();
>>>>>>
>>>>>> Node newProductNode = productDao.create(aProduct, session);
>>>>>>
>>>>>> session.save();
>>>>>>
>>>>>> utx.commit();
>>>>>>
>>>>>> If I step through the above code in debug within Eclipse, and
>>>>>> terminate the
>>>>>> Tomcat server after the first session.save() but before the
>>>>>> utx.commit(), I
>>>>>> can see that the the changes are made by the first Dao method call
>>>>>> userDao.create(aUser, session) are persisted.
>>>>>>
>>>>>> So far I have put all the required jotm jars in %TOMCAT_HOME%/lib
>>>>>> from the
>>>>>> distribution bundle jotm 2.1.4.
>>>>>>
>>>>>> My context.xml is configured with:
>>>>>>
>>>>>> <Transaction factory="org.objectweb.jotm.UserTransactionFactory"/>
>>>>>>
>>>>>>
>>>>>> My carol.properties is saved in WEB-INF/Classes and is as follows:
>>>>>>
>>>>>> # JNDI (Protocol Invocation)
>>>>>> carol.protocols=jrmp
>>>>>>
>>>>>> # Local RMI Invocation
>>>>>> carol.jvm.rmi.local.call=true
>>>>>>
>>>>>> # do not use CAROL JNDI wrapper
>>>>>> carol.start.jndi=false
>>>>>>
>>>>>> # do not start a name server
>>>>>> carol.start.ns=false
>>>>>>
>>>>>> # Naming Factory
>>>>>> carol.jndi.java.naming.factory.url.pkgs=org.apache.naming
>>>>>>
>>>>>>
>>>>>> Is there some further configuration required? No exceptions are
>>>>>> being
>>>>>> thrown any more and the UserTransaction is retrieved via JNDI
>>>>>> lookup
>>>>>> yet the
>>>>>> UserTranasction appears not to be functioning as expected.
>>>>>>
>>>>>> Any advice would be greatly appreciated. Thanks for your time.
>>>>>> Regards,
>>>>>>
>>>>>> James.
>>>>>>
>>>>>>
>>>>>>
>>>>>> Vijay Pandey wrote:
>>>>>>>
>>>>>>> There might be a line break and you might not be copying the full
>>>>>>> URL. I
>>>>>>> just checked and the URL is alive.
>>>>>>>
>>>>>>> -----Original Message-----
>>>>>>> From: Gadbury [mailto:[email protected]]
>>>>>>> Sent: Thursday, July 30, 2009 3:59 PM
>>>>>>> To: [email protected]
>>>>>>> Subject: RE: User Managed Transactions...
>>>>>>>
>>>>>>>
>>>>>>> Thank you Vijay, I shall take a closer look tomorrow. By the
>>>>>>> way,
>>>>>>> the
>>>>>>> second
>>>>>>> link gives me a 404.
>>>>>>>
>>>>>>> Cheers,
>>>>>>>
>>>>>>> James
>>>>>>>
>>>>>>>
>>>>>>> Vijay Pandey wrote:
>>>>>>>>
>>>>>>>> You might want to take a look at this
>>>>>>>>
>>>>>>>>
>>>>>>> http://static.raibledesigns.com/downloads/howto-tomcat-jotm.html#5.5-config
>>>>>>>>
>>>>>>>> along with this
>>>>>>>>
>>>>>>>>
>>>>>>> http://www.nabble.com/Re%3A-UserTransaction%2C-JOTM-and-Tomcat-5.5.x-p288894
>>>>>>>> 3.html
>>>>>>>>
>>>>>>>> Vijay
>>>>>>>>
>>>>>>>> -----Original Message-----
>>>>>>>> From: Gadbury [mailto:[email protected]]
>>>>>>>> Sent: Thursday, July 30, 2009 2:17 PM
>>>>>>>> To: [email protected]
>>>>>>>> Subject: Re: User Managed Transactions...
>>>>>>>>
>>>>>>>>
>>>>>>>> Hi again all.
>>>>>>>>
>>>>>>>> I have been trying to get javax.transaction.UserTransaction
>>>>>>>> working by
>>>>>>>> JNDI
>>>>>>>> lookup. I use Eclipse Galileo and Tomcat 6.0. I am trying
>>>>>>>> trying
>>>>>>>> retreive
>>>>>>>> a UserTransaction as follows (I have tried both):
>>>>>>>>
>>>>>>>> UserTransaction utx = new
>>>>>>>> InitialContext().lookup("java:comp/UserTransaction");
>>>>>>>>
>>>>>>>> UserTransaction utx = new
>>>>>>>> InitialContext().lookup("java:comp/env/UserTransaction");
>>>>>>>>
>>>>>>>> However, an exception is thrown stating that I must setup a
>>>>>>>> system
>>>>>>>> or
>>>>>>>> environment property, or the application context. Do I need to
>>>>>>>> configure
>>>>>>>> the resource and / or environment elements in context.xml? For
>>>>>>>> example,
>>>>>>>> the
>>>>>>>> resource configuration:
>>>>>>>>
>>>>>>>> <context>
>>>>>>>> <Resource name="UserTransaction" auth="Container"
>>>>>>>> type="javax.transaction.UserTransaction"/>
>>>>>>>> <ResourceParams name="UserTransaction">
>>>>>>>> <parameter>
>>>>>>>> <name>factory</name>
>>>>>>>> <value>org.objectweb.jotm.UserTransactionFactory</value>
>>>>>>>> </parameter>
>>>>>>>> <parameter>
>>>>>>>> <name>jotm.timeout</name>
>>>>>>>> <value>60</value>
>>>>>>>> </parameter>
>>>>>>>> </ResourceParams>
>>>>>>>> </context>
>>>>>>>>
>>>>>>>> Does Tomcat 6.0 support UserTransaction by JNDI, or do I need to
>>>>>>>> use
>>>>>>>> another
>>>>>>>> technology such as JOTM or Jencks? Ideally I wouldn't have to
>>>>>>>> install
>>>>>>>> and
>>>>>>>> configure one of the other technologies.
>>>>>>>>
>>>>>>>> Thanks for reading. Kind regards,
>>>>>>>>
>>>>>>>> James
>>>>>>>> --
>>>>>>>> View this message in context:
>>>>>>>>
>>>>>>> http://www.nabble.com/User-Managed-Transactions...-tp24687924p24745618.html
>>>>>>>> Sent from the Jackrabbit - Users mailing list archive at
>>>>>>>> Nabble.com.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> View this message in context:
>>>>>>> http://www.nabble.com/User-Managed-Transactions...-tp24687924p24747221.html
>>>>>>> Sent from the Jackrabbit - Users mailing list archive at
>>>>>>> Nabble.com.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>
>>>>>> --
>>>>>> View this message in context:
>>>>>> http://www.nabble.com/User-Managed-Transactions...-tp24687924p24759260.html
>>>>>> Sent from the Jackrabbit - Users mailing list archive at
>>>>>> Nabble.com.
>>>>>>
>>>>>
>>>>>
>>>>>
>>>>
>>>> --
>>>> View this message in context:
>>>> http://www.nabble.com/User-Managed-Transactions...-tp24687924p24768096.html
>>>> Sent from the Jackrabbit - Users mailing list archive at Nabble.com.
>>>>
>>>
>>>
>>>
>>
>> --
>> View this message in context:
>> http://www.nabble.com/User-Managed-Transactions...-tp24687924p24788686.html
>> Sent from the Jackrabbit - Users mailing list archive at Nabble.com.
>>
>
>
>
--
View this message in context:
http://www.nabble.com/User-Managed-Transactions...-tp24687924p24792235.html
Sent from the Jackrabbit - Users mailing list archive at Nabble.com.