how to get XADatasource using JNDI look up for Atomikos Transaction Management - spring

I am configuring Atomikios TM API with my Spring Application to achieve global transaction. As Atomikios require XADatasource to work, so I have done JNDI look up to get the same. But, unfortunately I am getting following errors while doing the look up.
Object of type [class com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource] available at JNDI location [jdbc/cuds] is not assignable to [javax.sql.XADataSource]
<jee:jndi-lookup id="dataSourceCu" jndi-name="jdbc/cuds" cache="true" resource-ref="true" lookup-on-startup="true" expected-type="javax.sql.XADataSource" />
<jee:jndi-lookup id="dataSourceGodb" jndi-name="jdbc/pushpullds" cache="true" resource-ref="true" lookup-on-startup="true" expected-type="javax.sql.XADataSource" />
I am using Spring 3.0/ hibernate with WebSphere 7.0.Where I am doing wrong. Please help me. Thanks.

The data source configured under jdbc/cuds is not an XADataSource but a normal one. You need to change the data source configuration in WebSphere (I have no idea how to do this).
However since you're on WebSphere which has it's own transaction manager there really is no need for configuring Atomikios. You can either use
<tx:jta-transaction-manager>
or org.springframework.transaction.jta.JtaTransactionManager / org.springframework.transaction.jta.WebSphereUowTransactionManager but the data source still needs to be XA.

XADataSource defines a contract between a JDBC provider and the application server and can only be used in that context. The DataSource object that you get when looking up the data source via JNDI in your application will never implement the XADataSource interface, even if the underlying data source is configured to support XA.
If you want to use your own transaction manager, then you would also have to manage the data sources yourself. Note that personally I wouldn't do that and strongly advice to use WebSphere's transaction manager instead. The reason is that distributed transactions involve lots of subtleties (e.g. recovery and in-doubt transactions) and it is unlikely that setting up a transaction manager inside an application would achieve the same level of robustness as WebSphere's transaction manager.

Related

Please configure a TransactionTemplate on the transacted policy

I implement a Spring Boot (1.5.x) application with Apache Camel (2.19)
For integration purposes I need to use three data sources (see for more about multi-data-sources here: https://github.com/spring-projects/spring-data-examples/tree/master/jpa/multiple-datasources).
One of the routes I have marked with .transacted():
from(Consts.DIRECT_ROUTE + routeId)
.routeId(routeId)
.startupOrder(loadRouteParameters.getStartupOrderTransformAndLoad())
.autoStartup(true)
.transacted()
however, when I start the app I get:
Caused by: java.lang.IllegalArgumentException: Found 3 PlatformTransactionManager in registry. Cannot determine which one to use. Please configure a TransactionTemplate on the transacted policy.
How to handle it? How to fulfill "Please configure a TransactionTemplate". I was not able to find any example for this special case.
Sounds like you have multiple TransactionManager beans in your Spring context. Camel does not know which one to take. You have to help your Camel a bit.
Define a SpringTransactionPolicy and reference the TransactionManager to be used in the Camel route.
<bean id="txPolicyName" class="org.apache.camel.spring.spi.SpringTransactionPolicy">
<property name="transactionManager" ref="[yourTxManagerBeanId]" />
</bean>
Then you can set the policy as argument to your transacted() in the Camel route:
.transacted("txPolicyName") // txPolicyBeanId as String

What's the differences between this Infinispan cache factories for Hibernate second level cache?

I'm trying to figure out the difference between this factories, used in hibernate.cache.region.factory_class property.
Example:
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.infinispan.JndiInfinispanRegionFactory" />
<property name="hibernate.cache.infinispan.cachemanager" value="java:jboss/infinispan/container/hibernate" />
There are 4 possible options.
The 2 options that I know something about is:
org.hibernate.cache.infinispan.InfinispanRegionFactory: for standalone aplications (not in a cluster, I think).
org.hibernate.cache.infinispan.JndiInfinispanRegionFactory: this is bounded to a JNDI in the property hibernate.cache.infinispan.cachemanager.
And I don't have any idea about these 2:
org.jboss.as.jpa.hibernate5.infinispan.SharedInfinispanRegionFactory: ?
org.jboss.as.jpa.hibernate5.infinispan.InfinispanRegionFactory: ?
We have a cluster configured on Wildfly 10.1.0 using domain mode. We want to share the entity cache among the nodes and we are having some doubts about how to do that.
If you're using Wildfly, you don't have to worry about setting the region factory class because Wildfly uses Infinispan as second-level cache provider by default. It's all explained here.
All you have to do is enable hibernate.cache.use_second_level_cache and you're good to go. See examples in the docu.
I agree with Galder, +1!
Regarding the purpose of [org.jboss.as.jpa.hibernate5.infinispan.SharedInfinispanRegionFactory][1] + [org.jboss.as.jpa.hibernate5.infinispan.InfinispanRegionFactory][2], these classes extend the Hibernate ORM [hibernate-infinispan][3] implementation classes, the purpose being to start the internal WildFly Infinispan cache services used for the JPA second level caching. They also deal with configuration as well. The below links may become outdated over time, as I think we [3] code might move to the Infinispan project (eventually).
A little more of the related code is at [HibernateSecondLevelCache.java][4], which backs up what Galder said. You can see that the WildFly JPA container automatically is setting the region factory class for you (if caching is enabled via [HibernatePersistenceProviderAdaptor.java][5].
I'm not sure if the code links are helpful to you, I thought they might be. :)
As a stackoverflow newbie, I am not allowed to post with more than 2 links, which is why [3] - [5] are invalid links.
Scott
[1] https://github.com/wildfly/wildfly/blob/master/jpa/hibernate5/src/main/java/org/jboss/as/jpa/hibernate5/infinispan/SharedInfinispanRegionFactory.java
[2] https://github.com/wildfly/wildfly/blob/master/jpa/hibernate5/src/main/java/org/jboss/as/jpa/hibernate5/infinispan/InfinispanRegionFactory.java
[3] github.com/hibernate/hibernate-orm/tree/master/hibernate-infinispan
[4] github.com/wildfly/wildfly/blob/master/jpa/hibernate5/src/main/java/org/jboss/as/jpa/hibernate5/HibernateSecondLevelCache.java
[5] github.com/wildfly/wildfly/blob/master/jpa/hibernate5/src/main/java/org/jboss/as/jpa/hibernate5/HibernatePersistenceProviderAdaptor.java#L91
The configuration envolves Infinispan, Hibernate and JGroups.
Using domain-mode on Wildfly10 you'll need this configuration on your application EAR:
<property name="hibernate.cache.use_second_level_cache" value="true"/>
Your server group need to use a profile that has the ha resources(high availability) such as full-ha or ha profiles. These profiles have the Infinispan and JGroups default configuration.
Then, you need to have the private 'Network Interfaces' on ALL Hosts' configuration that share the cache. JGroups uses the private Edit the domain/configuration/host.xml or use the wildfly console admin to add this configuration (200.0.0.171 needs to be replaced by the server's IP):
<interfaces>
...
<interface name="private">
<inet-address value="${jboss.bind.address.private:200.0.0.171}"/>
</interface>
<!-- .... -->
</interfaces>
For example, supposing you have a HostController HC1(with server-1 and server-2) and HC2(with server-3 and server-4)
Starting all the servers and Host Controllers, you'll see on your server.log:
INFO [org.infinispan.remoting.transport.jgroups.JGroupsTransport] (MSC service thread 1-4) ISPN000078: Starting JGroups channel hibernate
....
....
Received new cluster view for channel hibernate: [HC1:server-1, HC2-server-2, HC2-server-3, HC2-server-4]

Spring session with JDBC integration

I am new in Spring Session and want to use embedded database to store session information. I follow all the steps in
http://docs.spring.io/spring-session/docs/current/reference/html5/guides/httpsession-jdbc.html using spring-session-jdbc of version 1.2.0.but using Spring-web of 3.2.4 only
The following error is shown repeatly:
Caused by: org.postgresql.util.PSQLException: ERROR: relation "spring_session" does not exist 'Position: 13
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2198)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1927)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:561)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:419)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:365)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeUpdate(NewProxyPreparedStatement.java:105)
at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:824)
at org.springframework.jdbc.core.JdbcTemplate$2.doInPreparedStatement(JdbcTemplate.java:818)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:589)
... 21 more'
This issue already haunted me for days. Please help.
Here is the xml configuration
<bean class="org.springframework.session.jdbc.config.annotation.web.http.JdbcHttpSessi‌​onConfiguration"/>
<jdbc:embedded-database id="dataSource02" type="H2">
<jdbc:script location="classpath:org/springframework/session/jdbc/schema-h2.sql"/>
</jdbc:embedded-database>
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource02"/>
</bean>
Your problem stems from the fact that you use multiple data sources, since the provided stacktrace includes PostgreSQL JDBC driver classes while you are configuring a secondary, embedded data source to storing sessions.
Spring Session configuration picks up your primary data source (PostgreSQL) and expects to find session tables there.
I'd suggest you to use your primary data source to store session data, but if you insist on having secondary/embedded data source for that purpose you need to override JdbcOperationsSessionRepository bean provided by JdbcHttpSessionConfiguration#sessionRepository with your own instance which is created using your secondary data source and its appropriate tra saction manager. Note that bean must be named sessionRepository in order to override one from JdbcHttpSessionConfiguration.

Unable to proxy a JBossMQ queue in Spring

Spring JMS going against a JBoss 4.x JBossMQ queue (I know, old JBoss, JBossMQ superseded by JBoss Messaging, but I can't change the stack). Everything works when the Spring JMS configuration is loaded at startup, but when I make the JNDI lookups lazy, so that they are first loaded when I want to send a JMS message, I get the following exception:
org.springframework.jms.InvalidDestinationException: Destination is not an instance of SpyDestination QUEUE.myQueueName; nested exception is javax.jms.InvalidDestinationException: Destination is not an instance of SpyDestination QUEUE.myQueueName
at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:285)
My config:
<jee:jndi-lookup id="beanNameForMyQueue"
jndi-name="queue/myQueueName"
resource-ref="true" environment-ref="jndiEnvironment"
lookup-on-startup="false" cache="true" proxy-interface="javax.jms.Queue" />
I found a JBoss JIRA on this, and this similar HornetQ post, but so far no dice.
Am I just out of luck with the lazy init, or is there a workaround?

Where to store database passwords in a spring application or use JNDI?

Seems like a simple task. I have a webapp which requires a database connection. I'd like to be able to drop an updated .war file on this app server and load a new version without having to re-edit an applicationConfig.xml file to specify the database connection parameters for production.
Is using the container to setup the data source and then referencing it from JNDI the preferred way to go? I think it is cleaner having it all defined in the spring .xml file, but I can't come up with a clean way to allow the production password to be set only once as we roll out new versions.
So, how do you specify your database connection information in a spring application so that you can upgrade it without having to re-edit the files?
If you use JNDI, how do you handle setting up of your tests since the JNDI is not going to be available outside of the container?
Thanks!
The typical way to externalize database connection properties is to store them in a .properties file and load using <context:property-placeholder .../> . Then you can have different .properties files for testing and production.
If you choose JNDI, you can use a Spring's mock JNDI support for testing.
One approach is for your Spring configuration file to be composed of fragments related to specific layers in your application.
One such fragment could contain your DataSource defintion. For production, this fragment would use a jee:jndi-lookup. And then for test, have a different fragment would use a DriverManagerDataSource ?
Update:
If you want to change the datasource after deployment, then you can use this technique, along with changing the which datasource is injected into your other beans using a PropertyPlaceholderConfigurer as explained in an old post I wrote
eg:
<bean class="foo.bar.SomeClassNeedingDataSource"">
<property name="dataSource" ref="${the.datasource.to.inject}" />
</bean>
<jee:jndi-lookup id="jndiDataSource" ... />
<bean id="driverManagerDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
...
</bean>
# the properties file
the.datasource.to.inject = jndiDataSource
#the.datasource.to.inject = driverManagerDataSource

Resources