BTM, Spring and Tomcat

classic Classic list List threaded Threaded
20 messages Options
Reply | Threaded
Open this post in threaded view
|

BTM, Spring and Tomcat

Helder Sousa
Hi,

I setup an environment with BTM 1.3.2 and Spring 2.5 with Hibernate. When running in command line all works fine.
Then I configure the tomcat following the instructions in http://docs.codehaus.org/display/BTM/Tomcat13
When I try to run in tomcat a have this error:

Caused by: bitronix.tm.utils.InitializationException: cannot open disk journal
        at bitronix.tm.BitronixTransactionManager.<init>(BitronixTransactionManager.java:61)
        at bitronix.tm.TransactionManagerServices.getTransactionManager(TransactionManagerServices.java:41)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:115)
        ... 36 more
Caused by: java.io.IOException: The process cannot access the file because another process has locked a portion of the file
        at java.io.RandomAccessFile.read(Native Method)
        at java.io.RandomAccessFile.readInt(RandomAccessFile.java:720)
        at bitronix.tm.journal.TransactionLogHeader.<init>(TransactionLogHeader.java:77)
        at bitronix.tm.journal.TransactionLogAppender.<init>(TransactionLogAppender.java:50)
        at bitronix.tm.journal.DiskJournal.open(DiskJournal.java:131)
        at bitronix.tm.BitronixTransactionManager.<init>(BitronixTransactionManager.java:47)
        ... 42 more

Here it is the tomcat log: tomcatLog.txt
What is the problem?
Cheers,

Helder Sousa

Reply | Threaded
Open this post in threaded view
|

Re: BTM, Spring and Tomcat

Ludovic Orban
Administrator
Hi,

The error message is pretty much self-describing: BTM cannot open its journal log files because they've already been opened (and locked) by some other instance, most probably because BTM has been deployed twice.

This definitely is the case you ran into: you configured the tomcat55.BTMLifecycleListener to start up BTM together with Tomcat but you also configured Spring to start it up.

You need to choose where you want BTM to be managed: either in Spring or in Tomcat but not both. If you go for the Tomcat solution, replacing your bitronixTransactionManager with a JNDI lookup like this:

<bean id="bitronixTransactionManager" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:comp/UserTransaction"/>
</bean>

should suffice. If you want Spring to manage it, just get rid of the Tomcat integration.

Ludovic
Reply | Threaded
Open this post in threaded view
|

Re: BTM, Spring and Tomcat

Helder Sousa
Hi Ludovic,

Thank you for your help.
I need the spring integration so I rid of tomcat integration but then I have a new error.
Let me explain my spring configuration:
Firts I have the transaction manager configuration:

       
        <bean id="jtaTransactionManager"
                class="org.springframework.transaction.jta.JtaTransactionManager"
                depends-on="bitronixTransactionManager">
                <property name="transactionManager"
                        ref="bitronixTransactionManager" />
                <property name="userTransaction"
                        ref="bitronixTransactionManager" />
        </bean>

       
        <bean id="btmConfig" class="bitronix.tm.TransactionManagerServices"
                factory-method="getConfiguration">
                <property name="serverId" value="spring-btm" />
        </bean>

       
        <bean id="bitronixTransactionManager"
                class="bitronix.tm.TransactionManagerServices"
                factory-method="getTransactionManager"
                depends-on="btmConfig" destroy-method="shutdown" />

Then I have the datasource definition:
        <bean id="dataSource"
                class="bitronix.tm.resource.jdbc.PoolingDataSource" init-method="init"
                destroy-method="close">
                <property name="className" value="oracle.jdbc.xa.client.OracleXADataSource" />
                <property name="uniqueName" value="<b>jdbc/ds" />
                <property name="minPoolSize" value="1" />
                <property name="maxPoolSize" value="10" />
                <property name="acquisitionInterval" value="1" />
                <property name="acquisitionTimeout" value="15" />
                <property name="maxIdleTime" value="15" />
                <property name="useTmJoin" value="true" />
                <property name="deferConnectionRelease" value="true" />
                <property name="automaticEnlistingEnabled" value="true" />
                <property name="allowLocalTransactions" value="true" />
                <property name="driverProperties" ref="driverProperties" />
        </bean>
       
        <util:map id="driverProperties">
                <entry key="user" value="XXXXX" />
                <entry key="password" value="XXXXX" />
                <entry key="URL" value="jdbc:oracle:thin:@192.168.0.1:1521:DB" />
        </util:map>       

Finally the Hibernate Factory:

        <beans:bean id="alertHBSFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" depends-on="dataSource">
                <beans:property name="useTransactionAwareDataSource" value="true" />
                <beans:property name="annotatedClasses">
                        <beans:list>
                                <beans:value>
                                        com.alert.adt.ci.ContactPhoneHist
                                </beans:value>
                        </beans:list>
                </beans:property>
                <beans:property name="hibernateProperties">
                        <beans:map>
                                <beans:entry key="hibernate.dialect" value="org.hibernate.dialect.OracleDialect" />
                                <beans:entry key="hibernate.show_sql" value="false" />
                                <beans:entry key="hibernate.format_sql" value="false" />
                                <beans:entry key="hibernate.generate_statistics" value="false" />
                                <beans:entry key="hibernate.bytecode.use_reflection_optimizer" value="false" />
                                <beans:entry key="hibernate.current_session_context_class" value="jta" />
                                <beans:entry key="hibernate.connection.datasource" value="<b>jdbc/ds" />
                                <beans:entry key="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider" />
                                <beans:entry key="hibernate.transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory" />
                                <beans:entry key="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.BTMTransactionManagerLookup" />
                                <beans:entry key="hibernate.transaction.auto_close_session" value="true" />
                                <beans:entry key="hibernate.transaction.flush_before_completion" value="true" />
                                <beans:entry key="hibernate.connection.release_mode" value="auto" />
                        </beans:map>
                </beans:property>
        </beans:bean>

The error is about datasource.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'alertHBSFactory' defined in class path resource [mergedConfiguration.xml]: Invocation of init method failed; nested exception is org.hibernate.HibernateException: Could not find datasource
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1338)
        ...
Caused by: org.hibernate.HibernateException: Could not find datasource
        at org.hibernate.connection.DatasourceConnectionProvider.configure(DatasourceConnectionProvider.java:79)
        at org.hibernate.connection.ConnectionProviderFactory.newConnectionProvider(ConnectionProviderFactory.java:137)
        at org.hibernate.connection.ConnectionProviderFactory.newConnectionProvider(ConnectionProviderFactory.java:79)
        ...
Caused by: javax.naming.NameNotFoundException: Name jdbc is not bound in this Context
        at org.apache.naming.NamingContext.lookup(NamingContext.java:770)
        at org.apache.naming.NamingContext.lookup(NamingContext.java:153)
        at org.apache.naming.SelectorContext.lookup(SelectorContext.java:137)
        at javax.naming.InitialContext.lookup(InitialContext.java:392)
        at org.hibernate.connection.DatasourceConnectionProvider.configure(DatasourceConnectionProvider.java:75)
        ... 42 more

I seems that the JNDI datasource it not well configured.
I tried to create a file jndi.properties in my src directory with the content:

java.naming.factory.initial=bitronix.tm.jndi.BitronixInitialContextFactory

but the error still the same.
Best regards,

Helder Sousa


Ludovic Orban wrote
Hi,

The error message is pretty much self-describing: BTM cannot open its journal log files because they've already been opened (and locked) by some other instance, most probably because BTM has been deployed twice.

This definitely is the case you ran into: you configured the tomcat55.BTMLifecycleListener to start up BTM together with Tomcat but you also configured Spring to start it up.

You need to choose where you want BTM to be managed: either in Spring or in Tomcat but not both. If you go for the Tomcat solution, replacing your bitronixTransactionManager with a JNDI lookup like this:

<bean id="bitronixTransactionManager" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:comp/UserTransaction"/>
</bean>

should suffice. If you want Spring to manage it, just get rid of the Tomcat integration.

Ludovic
Reply | Threaded
Open this post in threaded view
|

RE: BTM, Spring and Tomcat

steveAtSignet
In reply to this post by Helder Sousa
Helder, I think you should add this to you Hibernate session factory
config:

<property name="dataSource" ref="dataSource"/>

That's what mine does anyway.

-----Original Message-----
From: Helder Sousa [mailto:[hidden email]]
Sent: 09 December 2008 17:35
To: [hidden email]
Subject: Re: [btm-user] BTM, Spring and Tomcat


Hi Ludovic,

Thank you for your help.
I need the spring integration so I rid of tomcat integration but then I
have a new error.
Let me explain my spring configuration:
Firts I have the transaction manager configuration:

        <!-- Spring JtaTransactionManager -->
        <bean id="jtaTransactionManager"
       
class="org.springframework.transaction.jta.JtaTransactionManager"
                depends-on="bitronixTransactionManager">
                <property name="transactionManager"
                        ref="bitronixTransactionManager" />
                <property name="userTransaction"
                        ref="bitronixTransactionManager" />
        </bean>

        <!--  Bitronix Transaction Manager embedded configuration -->
        <bean id="btmConfig"
class="bitronix.tm.TransactionManagerServices"
                factory-method="getConfiguration">
                <property name="serverId" value="spring-btm" />
        </bean>

        <!-- create Bitronix Transaction Manager transaction manager -->
        <bean id="bitronixTransactionManager"
                class="bitronix.tm.TransactionManagerServices"
                factory-method="getTransactionManager"
                depends-on="btmConfig" destroy-method="shutdown" />

Then I have the datasource definition:
        <bean id="dataSource"
                class="bitronix.tm.resource.jdbc.PoolingDataSource"
init-method="init"
                destroy-method="close">
                <property name="className"
value="oracle.jdbc.xa.client.OracleXADataSource" />
                <property name="uniqueName" value="jdbc/ds" />
                <property name="minPoolSize" value="1" />
                <property name="maxPoolSize" value="10" />
                <property name="acquisitionInterval" value="1" />
                <property name="acquisitionTimeout" value="15" />
                <property name="maxIdleTime" value="15" />
                <property name="useTmJoin" value="true" />
                <property name="deferConnectionRelease" value="true" />
                <property name="automaticEnlistingEnabled" value="true"
/>
                <property name="allowLocalTransactions" value="true" />
                <property name="driverProperties" ref="driverProperties"
/>
        </bean>
       
        <util:map id="driverProperties">
                <entry key="user" value="XXXXX" />
                <entry key="password" value="XXXXX" />
                <entry key="URL"
value="jdbc:oracle:thin:@192.168.0.1:1521:DB" />
        </util:map>

Finally the Hibernate Factory:

        <beans:bean id="alertHBSFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFa
ctoryBean"
depends-on="dataSource">
                <beans:property name="useTransactionAwareDataSource"
value="true" />
                <beans:property name="annotatedClasses">
                        <beans:list>
                                <beans:value>
       
com.alert.adt.ci.ContactPhoneHist
                                </beans:value>
                        </beans:list>
                </beans:property>
                <beans:property name="hibernateProperties">
                        <beans:map>
                                <beans:entry key="hibernate.dialect"
value="org.hibernate.dialect.OracleDialect" />
                                <beans:entry key="hibernate.show_sql"
value="false" />
                                <beans:entry key="hibernate.format_sql"
value="false" />
                                <beans:entry
key="hibernate.generate_statistics" value="false" />
                                <beans:entry
key="hibernate.bytecode.use_reflection_optimizer"
value="false" />
                                <beans:entry
key="hibernate.current_session_context_class" value="jta"
/>
                                <beans:entry
key="hibernate.connection.datasource" value="jdbc/ds" />
                                <beans:entry
key="hibernate.cache.provider_class"
value="org.hibernate.cache.NoCacheProvider" />
                                <beans:entry
key="hibernate.transaction.factory_class"
value="org.hibernate.transaction.JTATransactionFactory" />
                                <beans:entry
key="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.BTMTransactionManagerLookup" />
                                <beans:entry
key="hibernate.transaction.auto_close_session" value="true"
/>
                                <beans:entry
key="hibernate.transaction.flush_before_completion"
value="true" />
                                <beans:entry
key="hibernate.connection.release_mode" value="auto" />
                        </beans:map>
                </beans:property>
        </beans:bean>

The error is about datasource.

org.springframework.beans.factory.BeanCreationException: Error creating
bean with name 'alertHBSFactory' defined in class path resource
[mergedConfiguration.xml]: Invocation of init method failed; nested
exception is org.hibernate.HibernateException: Could not find datasource
        at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFac
tory.initializeBean(AbstractAutowireCapableBeanFactory.java:1338)
        ...
Caused by: org.hibernate.HibernateException: Could not find datasource
        at
org.hibernate.connection.DatasourceConnectionProvider.configure(Datasour
ceConnectionProvider.java:79)
        at
org.hibernate.connection.ConnectionProviderFactory.newConnectionProvider
(ConnectionProviderFactory.java:137)
        at
org.hibernate.connection.ConnectionProviderFactory.newConnectionProvider
(ConnectionProviderFactory.java:79)
        ...
Caused by: javax.naming.NameNotFoundException: Name jdbc is not bound in
this Context
        at
org.apache.naming.NamingContext.lookup(NamingContext.java:770)
        at
org.apache.naming.NamingContext.lookup(NamingContext.java:153)
        at
org.apache.naming.SelectorContext.lookup(SelectorContext.java:137)
        at javax.naming.InitialContext.lookup(InitialContext.java:392)
        at
org.hibernate.connection.DatasourceConnectionProvider.configure(Datasour
ceConnectionProvider.java:75)
        ... 42 more

I seems that the JNDI datasource it not well configured.
I tried to create a file jndi.properties in my src directory with the
content:

java.naming.factory.initial=bitronix.tm.jndi.BitronixInitialContextFacto
ry

but the error still the same.
Best regards,

Helder Sousa



Ludovic Orban wrote:
>
> Hi,
>
> The error message is pretty much self-describing: BTM cannot open its
> journal log files because they've already been opened (and locked) by
> some other instance, most probably because BTM has been deployed
twice.
>
> This definitely is the case you ran into: you configured the
> tomcat55.BTMLifecycleListener to start up BTM together with Tomcat but

> you also configured Spring to start it up.
>
> You need to choose where you want BTM to be managed: either in Spring
> or in Tomcat but not both. If you go for the Tomcat solution,
> replacing your bitronixTransactionManager with a JNDI lookup like
this:

>
> <bean id="bitronixTransactionManager"
> class="org.springframework.jndi.JndiObjectFactoryBean">
>     <property name="jndiName" value="java:comp/UserTransaction"/>
> </bean>
>
> should suffice. If you want Spring to manage it, just get rid of the
> Tomcat integration.
>
> Ludovic
>

--
View this message in context:
http://www.nabble.com/BTM%2C-Spring-and-Tomcat-tp20917679p20919538.html
Sent from the Bitronix Transaction Manager mailing list archive at
Nabble.com.


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: BTM, Spring and Tomcat

Ludovic Orban
Administrator
In reply to this post by Helder Sousa
This is because Hibernate will try to look up the datasource from Tomcat's JNDI. Add this to your hibernateProperties to force Hibernate to look it up from BTM's JNDI:

<beans:entry key="hibernate.jndi.class" value="bitronix.tm.jndi.BitronixInitialContextFactory" />

Now I'm not sure you won't run into the same problem for the hibernate.transaction.manager_lookup_class as I'm not sure org.hibernate.transaction.BTMTransactionManagerLookup will look the TM up from the Tomcat JNDI or BTM's one.

Is it really mandatory for you to have the TM configured in Spring ? If you integrated the TM in Tomcat and looked it up from there instead of creating it from Spring you would not have those JNDI issues.
Reply | Threaded
Open this post in threaded view
|

RE: BTM, Spring and Tomcat

Ludovic Orban
Administrator
In reply to this post by steveAtSignet
That's a good suggestion that will work too.

Do you know by chance if BTMTransactionManagerLookup will cause a problem or not ?
Reply | Threaded
Open this post in threaded view
|

RE: BTM, Spring and Tomcat

steveAtSignet
In reply to this post by Helder Sousa
This is what my Hibernate session factory looks like, and works fine:

<!-- Hibernate SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFa
ctoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="annotatedClasses">
                <list>
       
<value>com.signetgroupplc.edm.domain.TestEntity</value>
                </list>
        </property>
        <property name="hibernateProperties">
                <props>

                        <prop
key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
                        <!-- <prop
key="hibernate.dialect">org.hibernate.dialect.DB2400Dialect</prop> -->
                        <prop key="hibernate.hbm2ddl.auto">update</prop>
                        <prop
key="hibernate.current_session_context_class">jta</prop>
                        <prop
key="hibernate.transaction.factory_class">org.hibernate.transaction.JTAT
ransactionFactory</prop>
                        <prop
key="hibernate.transaction.manager_lookup_class">org.hibernate.transacti
on.BTMTransactionManagerLookup</prop>
                        <!-- Hibernate now requires that the transaction
manager be looked-up via JNDI -->
                        <prop
key="hibernate.jndi.class">bitronix.tm.jndi.BitronixInitialContextFactor
y</prop>
                        <!-- Connections should generally be released
this way for JTA anyway,
                                but this is also needed because of a bug
in this release of BTM (1.3.2) -->
                        <prop
key="hibernate.connection.release_mode">after_statement</prop>
                        <prop
key="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider
</prop>
                        <prop key="hibernate.show_sql">false</prop>
                </props>
        </property>
</bean>


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

RE: BTM, Spring and Tomcat

Helder Sousa
Hi all :)

Thank you for your tips.

I almost get this working.
First, and to answer to Ludovic, I have to use Spring to manage transactions. I don't want to implement any kind of beginTransaction/commit/rollback code. So, my approach is based in Spring. I rid of BTM configuration from tomcat.

Regarding dataSource, I configured it on Tomcat and use it with JNDI in Spring configuration (I don't need the bitronix.tm.jndi.BitronixInitialContextFactory configuration in Hibernate SessionFactory).

<beans:bean id="myDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <beans:property name="jndiName" value="java:comp/env/jdbc/ds" />
</beans:bean>

and then I configure the property dataSource of Hibernate SessionFactory bean as sugested by Steve :)

Steve, about your sessionFactory configuration, I tried it but I had a problem. Running the code there is "loop" (I think it is in Hibernate code. They had a similar (or the same) bug http://opensource.atlassian.com/projects/hibernate/browse/HHH-3481)

15:57:30,509 TRACE JTATransactionFactory:159 - Attempting to locate UserTransaction via JNDI [java:comp/UserTransaction]
15:57:30,513 TRACE JTATransactionFactory:159 - Attempting to locate UserTransaction via JNDI [java:comp/UserTransaction]
15:57:30,514 TRACE JTATransactionFactory:159 - Attempting to locate UserTransaction via JNDI [java:comp/UserTransaction]
15:57:30,514 TRACE JTATransactionFactory:159 - Attempting to locate UserTransaction via JNDI [java:comp/UserTransaction]
15:57:30,515 TRACE JTATransactionFactory:159 - Attempting to locate UserTransaction via JNDI [java:comp/UserTransaction]
(... until a StackOverflow)

Although, I found a post in spring forums (last post of http://forum.springframework.org/showthread.php?p=215235), where Denis.Zhdanov said: "you explicitly configured jta transaction manager for hibernate and that's unnecessary. Spring binds hibernate contextual sessions to the spring transactions infrastructure out of the box. I.e. you shouldn't configure transactions at the hibernate level, just define necessary settings at the spring and make sure to have dao methods transactional"

So, with this information I removed the hibernate.transaction.factory_class property and I setup my hibernate properties like this:

        <property name="hibernateProperties">
                <map>
                        <entry key="hibernate.dialect" value="org.hibernate.dialect.OracleDialect" />
                        <entry key="hibernate.bytecode.use_reflection_optimizer" value="false" />
                        <entry key="hibernate.current_session_context_class" value="jta" />
                        <entry key="hibernate.transaction.auto_close_session" value="true" />
                        <entry key="hibernate.transaction.flush_before_completion" value="true" />
                        <entry key="hibernate.connection.release_mode" value="auto" />
                        <entry key="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider" />
                        <entry key="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.BTMTransactionManagerLookup" />
                </map>
        </property>

With this setup, I could run the code with without errors but with a big problem! Although there is some entries in the log about commit transaction, there is no records in database

Take a look to the transactionLog.txt

I even try to setup hibernate.connection.release_mode with the value "after_statement" like your hibernate sessionfactory but I still have same problem.
Can anyone explain me why the records are not in the database? Everything looks OK during execution!
Thank you for your help.

Hélder Sousa

P.S. Execution Environment:
- Spring: 2.5.6.
- Hibernate: 3.3.1.GA
- BTM: 1.3.2
- Oracle Driver: ojdbc14_g


steveAtSignet wrote
This is what my Hibernate session factory looks like, and works fine:


<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFa
ctoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="annotatedClasses">
                <list>
       
<value>com.signetgroupplc.edm.domain.TestEntity</value>
                </list>
        </property>
        <property name="hibernateProperties">
                <props>

                        <prop
key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
                       
                        <prop key="hibernate.hbm2ddl.auto">update</prop>
                        <prop
key="hibernate.current_session_context_class">jta</prop>
                        <prop
key="hibernate.transaction.factory_class">org.hibernate.transaction.JTAT
ransactionFactory</prop>
                        <prop
key="hibernate.transaction.manager_lookup_class">org.hibernate.transacti
on.BTMTransactionManagerLookup</prop>
                       
                        <prop
key="hibernate.jndi.class">bitronix.tm.jndi.BitronixInitialContextFactor
y</prop>
                       
                        <prop
key="hibernate.connection.release_mode">after_statement</prop>
                        <prop
key="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider
</prop>
                        <prop key="hibernate.show_sql">false</prop>
                </props>
        </property>
</bean> 


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

RE: BTM, Spring and Tomcat

steveAtSignet
The error message about "Attempting to locate UserTransaction..." was happening because the newer versions of Hibernate only allow for the transaction manager to be looked-up via JNDI. That's why you should use the property "hibernate.jndi.class" set to "bitronix.tm.jndi.BitronixInitialContextFactory".

I don't know about whether you need the "hibernate.transaction.factory_class" property or not as I haven't tried without it, but having it there didn't stop anything working for me.
Reply | Threaded
Open this post in threaded view
|

RE: BTM, Spring and Tomcat

Helder Sousa
Hi Steve,

Thank you for your feedback.
I configure that property but I don't see any differences.
The code executes as should, but there is no records in database yet.
Best regards,

Helder Sousa


steveAtSignet wrote
The error message about "Attempting to locate UserTransaction..." was happening because the newer versions of Hibernate only allow for the transaction manager to be looked-up via JNDI. That's why you should use the property "hibernate.jndi.class" set to "bitronix.tm.jndi.BitronixInitialContextFactory".

I don't know about whether you need the "hibernate.transaction.factory_class" property or not as I haven't tried without it, but having it there didn't stop anything working for me.
Reply | Threaded
Open this post in threaded view
|

RE: BTM, Spring and Tomcat

Simon-2745
In reply to this post by Helder Sousa

Hey Helder,

I recommend that just for testing and working out your problem you use
the bitronic, hibernate and direct datasource settings that I got
working in the attached spring configuration file.

If you take that file and delete my JMS beans from that config (delete
"xaJmsConnectionFactory" near the top and delete every bean *below*
"hibernateDao") then what you are left with is how to configure a
working hiberante DAO with a direct jdbc datasource. For my datasource I
was using an apache commons pool datasource and you might just use that
temporarily whilst you are debugging else you can temporary configure a
direct Oracle pooling datasource which included in your oracle drive
jar. I only recommend this to keep tomcat out of the picture for a
moment whilst you debug what is going on - then when you see it working
then remove the direct pool and try the pool from JNDI.

So that is my advice about how to proceed.

My explanation of how it works is follows:

You have a choice of which subclass of
org.springframework.transaction.support.AbstractPlatformTransactionManager
that you use with hibernate. You have two choices:
HibernateTransactionManager or JtaTransactionManager. If you want to
commit and rollback *only* what Hibernate is doing then it is most
efficient to use HibernateTransactionManager . If you want hibernate to
manage your database resource and you want it to participate in a global
user transaction that spans other resources (such as JMS queues or some
second database) then you needto use JtaTransactionManager but you have
to configure the Hibnerate session telling it how to register itself
with the Bitronix Transaction Manager to recieve commit or rollback
statements for the global transaction. This explains why in my
configuration file (attached) you can that the hibernate session has
properties set on it that name classes with "JTA" and "Bitronix" in
their name - that tells Hibernate how to register itself as a resource
with the Transaction Manager so that it may join the global transaction.
This is only half of the picture.

The other half of the picture is how you start a global transaction with
the bitronix transaction manager. In my configuration if we look at
rawHibernateDao and hibernateDao we can see that I am telling spring to
put a transaction begin/commit/rollback wrapper around every method of
my raw Hibernate DAO. The transactional wrapper hibernateDoa has a
reference to my jtaTransactionManger (which is Bitronix TM).

Putting it all together my understanding of how my configuration works
[and this is my fuzzy user view of what happens I am sure that someone
that know the Bitonix code might feel the need to correct or clarify me
here]:

1) the application code invokes a method on hibernateDao which is
actually a spring aop proxy object that first speaks to the JTA TM
asking to start a new tx or join an existing tx.
2) the tm ensures that the tx is bound to the thread
3) the thread eventually gets to the methods on the hibernate session.
the hibernate session speaks to the JTA TM to enlist itself within the
current global transaction.
4) if everything goes find eventually my rawHibernateDao returns
normally. at which point the aop proxy object tells the JTA TM to
commit. the JTA TM tells all the resources that enlisted in the
transaction to flush. if something goes wrong and an exception is thrown
it is caught with the aop proxy object and it tells the JTA TM to
rollback and the TM tells all that resource that enlisted in the
transaction to rollback.

I have one final piece of advice. Putting the transactional wrapper
around a DAO class is not always where it is needed. This is because it
only makes the DAO call atomic. Normally you need a transaction to span
a whole use case. A whole use case does not normally just have a single
DAO call - a use case normally has a couple of DAO calls to do something
useful to the user and if your needing global transactions to span a
database and a JMS call then your use cases must be including those
sorts of calls. So making a single DAO atomic is a bit odd. Normally
what is required is that I have a bean that uses the DOA and, say, a JMS
connection, and it is that bean (call it my business service bean) that
I want to put a transactional wrapper around. That way my UI code calls
my business service bean it is that bean that I wrap in my spring aop
proxy. The many DAO calls made by my business service bean will then all
be grouped into one transaction that spans the entire use case.

A good book that explains the those patterns and spring transactions is
"POJOs In Action" by Chris Richardson. It is a couple of years old so
the code snippets use older version of hibernate, Kodo JDO and EJB3 but
its explanation of the design patterns and its coverage of spring
transaction management is pretty good.

Kindest Regards,

Simon


On Wed, 10 Dec 2008 09:09:10 -0800 (PST), "Helder Sousa"
<[hidden email]> said:

>
> Hi all :)
>
> Thank you for your tips.
>
> I almost get this working.
> First, and to answer to Ludovic, I have to use Spring to manage
> transactions. I don't want to implement any kind of
> beginTransaction/commit/rollback code. So, my approach is based in
> Spring. I
> rid of BTM configuration from tomcat.
>
> Regarding dataSource, I configured it on Tomcat and use it with JNDI in
> Spring configuration (I don't need the
> bitronix.tm.jndi.BitronixInitialContextFactory configuration in Hibernate
> SessionFactory).
>
> <beans:bean id="myDataSource"
> class="org.springframework.jndi.JndiObjectFactoryBean">
> <beans:property name="jndiName" value="java:comp/env/jdbc/ds" />
> </beans:bean>
>
> and then I configure the property dataSource of Hibernate SessionFactory
> bean as sugested by Steve :)
>
> Steve, about your sessionFactory configuration, I tried it but I had a
> problem. Running the code there is "loop" (I think it is in Hibernate
> code.
> They had a similar (or the same) bug
> http://opensource.atlassian.com/projects/hibernate/browse/HHH-3481)
>
> 15:57:30,509 TRACE JTATransactionFactory:159 - Attempting to locate
> UserTransaction via JNDI [java:comp/UserTransaction]
> 15:57:30,513 TRACE JTATransactionFactory:159 - Attempting to locate
> UserTransaction via JNDI [java:comp/UserTransaction]
> 15:57:30,514 TRACE JTATransactionFactory:159 - Attempting to locate
> UserTransaction via JNDI [java:comp/UserTransaction]
> 15:57:30,514 TRACE JTATransactionFactory:159 - Attempting to locate
> UserTransaction via JNDI [java:comp/UserTransaction]
> 15:57:30,515 TRACE JTATransactionFactory:159 - Attempting to locate
> UserTransaction via JNDI [java:comp/UserTransaction]
> (... until a StackOverflow)
>
> Although, I found a post in spring forums (last post of
> http://forum.springframework.org/showthread.php?p=215235), where
> Denis.Zhdanov said: "you explicitly configured jta transaction manager
> for
> hibernate and that's unnecessary. Spring binds hibernate contextual
> sessions
> to the spring transactions infrastructure out of the box. I.e. you
> shouldn't
> configure transactions at the hibernate level, just define necessary
> settings at the spring and make sure to have dao methods transactional"
>
> So, with this information I removed the
> hibernate.transaction.factory_class
> property and I setup my hibernate properties like this:
>
> <property name="hibernateProperties">
> <map>
> <entry key="hibernate.dialect"
> value="org.hibernate.dialect.OracleDialect" />
> <entry key="hibernate.bytecode.use_reflection_optimizer" value="false" />
> <entry key="hibernate.current_session_context_class" value="jta" />
> <entry key="hibernate.transaction.auto_close_session" value="true" />
> <entry key="hibernate.transaction.flush_before_completion" value="true"
> />
> <entry key="hibernate.connection.release_mode" value="auto" />
> <entry key="hibernate.cache.provider_class"
> value="org.hibernate.cache.NoCacheProvider" />
> <entry key="hibernate.transaction.manager_lookup_class"
> value="org.hibernate.transaction.BTMTransactionManagerLookup" />
> </map>
> </property>
>
> With this setup, I could run the code with without errors but with a big
> problem! Although there is some entries in the log about commit
> transaction,
> there is no records in database :confused:
>
> Take a look to the
> http://www.nabble.com/file/p20939570/transactionLog.txt
> transactionLog.txt
>
> I even try to setup hibernate.connection.release_mode with the value
> "after_statement" like your hibernate sessionfactory but I still have
> same
> problem.
> Can anyone explain me why the records are not in the database? Everything
> looks OK during execution!
> Thank you for your help.
>
> Hélder Sousa
>
> P.S. Execution Environment:
> - Spring: 2.5.6.
> - Hibernate: 3.3.1.GA
> - BTM: 1.3.2
> - Oracle Driver: ojdbc14_g

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email

btm-mdp-hbm-context.xml (9K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

RE: BTM, Spring and Tomcat

Ludovic Orban
Administrator
In reply to this post by Helder Sousa
You've definitely made a classloader soup, you absolutely cannot have the TM configured in a classloader and the connection pools in another. But this is what you did.

Spring can manage transactions as long as it can get a reference to the TM so your argument for configuring the TM in Spring is bogus.

Either configure your datasources in the Spring config or integrate the TM back in Tomcat and replace it in your Spring config by a JNDI lookup. In the latter case alo make sure the BTM and JTA jars are not in your web-inf/lib folder.

And remember to put the hibernate.transaction.factory_class in place or you might run into troubles in some cases.
Reply | Threaded
Open this post in threaded view
|

Re: BTM, Spring and Tomcat

Simon-2745
Wow if I had a dollar for home many times have I seen J2EE classloaders
cause problems I would be a rich man...

So the problem is that J2EE containers such as Tomcat load
webapplications into a classloader setup for that purpose so that when
you leave the server running and redeploy the webapp the webapp
classloader can dump all the old classes in the old webapp and load all
the new classes in the new webapp. However if you put the datasource in
the container itself (in a higher classloader than the webapp) then put
the TransactionManager in the webapp then they have problems communicating.

Simon

Ludovic Orban wrote:

> You've definitely made a classloader soup, you absolutely cannot have the TM
> configured in a classloader and the connection pools in another. But this is
> what you did.
>
> Spring can manage transactions as long as it can get a reference to the TM
> so your argument for configuring the TM in Spring is bogus.
>
> Either configure your datasources in the Spring config or integrate the TM
> back in Tomcat and replace it in your Spring config by a JNDI lookup. In the
> latter case alo make sure the BTM and JTA jars are not in your web-inf/lib
> folder.
>
> And remember to put the hibernate.transaction.factory_class in place or you
> might run into troubles in some cases.
>  



---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

RE: BTM, Spring and Tomcat

Helder Sousa
In reply to this post by Ludovic Orban
You may have some reason with "classloader soup". So, I configured a commons dbcp datasource in spring and used a new fresh install of tomcat (without any custom configuration or extra jars in tomcat lib).
This way, all stuff is managed by Spring (JTA and datasource) and all needed jars are in web-inf/lib folder, but the behavior is the same... the code executes normally but the records are not persisted in database
Thank you for your time.
Best regards,

Helder Sousa


Ludovic Orban wrote
You've definitely made a classloader soup, you absolutely cannot have the TM configured in a classloader and the connection pools in another. But this is what you did.

Spring can manage transactions as long as it can get a reference to the TM so your argument for configuring the TM in Spring is bogus.

Either configure your datasources in the Spring config or integrate the TM back in Tomcat and replace it in your Spring config by a JNDI lookup. In the latter case alo make sure the BTM and JTA jars are not in your web-inf/lib folder.

And remember to put the hibernate.transaction.factory_class in place or you might run into troubles in some cases.
Reply | Threaded
Open this post in threaded view
|

RE: BTM, Spring and Tomcat

Ludovic Orban
Administrator
So you're trying to use BTM together with DBCP ? This ain't gonna work: the reason why BTM bundles connection pools is because a TM can only work with connection pools that have XA support.

Why don't you just configure your BTM connection pools and the transaction manager in Spring ?
Reply | Threaded
Open this post in threaded view
|

Re: BTM, Spring and Tomcat

Simon-2745
Ludovic,

Helder is using Hibernate and it is Hibernate that is to be XA aware
agent for the jdbc connection. The zip springjta-02.zip zip attached to
this thread http://forum.springframework.org/showthread.php?t=64523  has
code that proves the database transaction works if you have an XA aware
hibernate configuration managing a vanilla database connection.

Of course if you are not using hibernate then you are correct that only
BTM and DBCP wont work. The zip springjta-01.zip attached to that thread
above shows that you have to use something like your XA connection pool
implementation *not* DBCP.

I once tried to use an XA configured hibernate session configured to use
an Atomikos XA connection pool. This lead to a lot of stacktrace error
output when hibernate attempted to issue SET AUTOCOMMIT instructions to
the XA connection pool. They appeared to be fighting over who controls
the database resource.

rgds

Simon

Ludovic Orban wrote:
> So you're trying to use BTM together with DBCP ? This ain't gonna work: the
> reason why BTM bundles connection pools is because a TM can only work with
> connection pools that have XA support.
>
> Why don't you just configure your BTM connection pools and the transaction
> manager in Spring ?
>  


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: BTM, Spring and Tomcat

Ludovic Orban
Administrator
I haven't (yet) reviewed the application you posted on the spring forums but I can tell already you you're wrong.

Hibernate needs to integrate with the TM to control the lifecycle of its sessions and caches but you also must use the bundled BTM connection pool to get transactions working.

If you don't, spring might make it look like it is working but you application cannot be transactional: the connection pool has to have knowledge of XA and report to the TM about its activities. Not using the BTM connection pool means no XA transactions.
Reply | Threaded
Open this post in threaded view
|

Re: BTM, Spring and Tomcat

Simon-2745
Ludovic,

It is not that it looks like it is working but that it passes a junit
test that says that is supposed to test that it is working. That is the
only code - just to test
that if I through an exception the db and jms stuff is rolled back. I
did this because I was having problems getting it to work in real code
so I isolated it into an single example that prooves rollback work so
that I could find the configuration which works. There may be something
wrong with my test method so if you could please help me find it that
would be a great help. All you have to do is unzip the file, put
mvn.sh/mvn.bat on your path, set MAVEN_HOME and JAVA_HOME and run "mvn
test" to see the test run and succeed.

thx

Simon

Ludovic Orban wrote:

> I haven't (yet) reviewed the application you posted on the spring forums but
> I can tell already you you're wrong.
>
> Hibernate needs to integrate with the TM to control the lifecycle of its
> sessions and caches but you also must use the bundled BTM connection pool to
> get transactions working.
>
> If you don't, spring might make it look like it is working but you
> application cannot be transactional: the connection pool has to have
> knowledge of XA and report to the TM about its activities. Not using the BTM
> connection pool means no XA transactions.
>  



---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: BTM, Spring and Tomcat

Ludovic Orban
Administrator
Just replace your dataSource bean with this one:

<bean id="dataSource" class="bitronix.tm.resource.jdbc.PoolingDataSource" init-method="init" destroy-method="close">
    <property name="className" value="org.apache.derby.jdbc.EmbeddedXADataSource" />
    <property name="uniqueName" value="derby" />
    <property name="maxPoolSize" value="3" />
    <property name="driverProperties">
        <props>
            <prop key="databaseName">users1</prop>
            <prop key="createDatabase">create</prop>
        </props>
    </property>
</bean>

and get rid of this line in your xaJmsConnectionFactory:

<property name="allowLocalTransactions" value="true" />

and you should then have a full XA compliant application.
Reply | Threaded
Open this post in threaded view
|

Spring JTA + Spring Message Driven POJOs + Spring Hibernate Re: [btm-user] BTM, Spring and Tomcat

Simon-2745


Ludovic,

Thank you very much for taking the time to explain to me (offline) what
was going on in my tests that would make work under normal test
conditions but not be XA compliant.

I have attached a 1.0 version of the maven+eclipse project zip file. I
have tidied up the JUnit tests so that everything just runs and builds.
I have bumped the version of hibernate to 3.2.3.GA.

Kindest Regards,

Simon

On Sat, 13 Dec 2008 02:07:16 -0800 (PST), "Ludovic Orban"
<[hidden email]> said:

>
> Just replace your dataSource bean with this one:
>
> <bean id="dataSource" class="bitronix.tm.resource.jdbc.PoolingDataSource"
> init-method="init" destroy-method="close">
>     <property name="className"
> value="org.apache.derby.jdbc.EmbeddedXADataSource" />
>     <property name="uniqueName" value="derby" />
>     <property name="maxPoolSize" value="3" />
>     <property name="driverProperties">
>         <props>
>             <prop key="databaseName">users1</prop>
>             <prop key="createDatabase">create</prop>
>         </props>
>     </property>
> </bean>
>
> and get rid of this line in your xaJmsConnectionFactory:
>
> <property name="allowLocalTransactions" value="true" />
>
> and you should then have a full XA compliant application.
> --
> View this message in context:
> http://www.nabble.com/BTM%2C-Spring-and-Tomcat-tp20917679p20988802.html
> Sent from the Bitronix Transaction Manager mailing list archive at
> Nabble.com.
>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>     http://xircles.codehaus.org/manage_email
>
>

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email

springjta1.0.zip (33K) Download Attachment