Can't make JTA work on jboss AS7.1 with spring 3.1 - jpa

We're trying to configure a Spring application to work with JTA transactions. It is not like it is failing, but everything we tried just do the select and ignores our persistence operations.
As you can see in the following logs, even though the save statement run there’s no insert statement, neither an exception, neither an error/warning logs
server.log
DEBUG [xxxx.xxxx.persistence] (http--0.0.0.0-8080-1) execute $Proxy363.save(whatever.core.entities.XxxAssignedTime#51a8c542)
DEBUG [org.springframework.data.repository.core.support.TransactionalRepositoryProxyPostProcessor$CustomAnnotationTransactionAttributeSource] (http--0.0.0.0-8080-1) Adding transactional method 'save' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] (http--0.0.0.0-8080-1) Returning cached instance of singleton bean 'transactionManager'
DEBUG [org.springframework.transaction.jta.JtaTransactionManager] (http--0.0.0.0-8080-1) Participating in existing transaction
INFO [xxxx.xxxx.impl.BpmnUserBusinessImpl] (http--0.0.0.0-8080-1) Last Assigned Time Updated to *******, Thu Sep 06 15:48:48 ICT 2012
It is like thought the application server thinks everything went right. Whereas if you check the table no insertion or update was made.
The datasource that we intend to use with a spring application is successfully used with JTA transactions by a Java EE war application running in the same application server.
Since we have no idea where the problem might be I'd like to put it all in full context.
spring 3.1.2-RELEASE
hibernate 4.1.5.Final
spring-data-jpa 1.1.1.Final
apache axis 1.4
jboss AS7.1
DB: oracle 10g
We've been trying all sorts of crazy configuration in order to try to make it work, so I will just copy here the simplest one.
standalone.xml
<datasource jta="true" jndi-name="java:jboss/datasources/EngineDS" pool-name="EngineDS" enabled="true" use-java-context="true" use-ccm="true">
<connection-url>jdbc:oracle:thin:#server:port:****</connection-url>
<driver>oracle</driver>
<transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
<pool>
<min-pool-size>10</min-pool-size>
<max-pool-size>100</max-pool-size>
<prefill>true</prefill>
</pool>
<security>
<user-name>****</user-name>
<password>****</password>
</security>
<statement>
<prepared-statement-cache-size>32</prepared-statement-cache-size>
<share-prepared-statements>true</share-prepared-statements>
</statement>
</datasource>
<drivers>
<driver name="oracle" module="com.oracle.ojdbc6">
<xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
</driver>
</drivers>
web.xml
[...]
<resource-ref id="DS">
<res-ref-name>EngineDS</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
<mapped-name>java:jboss/datasources/EngineDS</mapped-name>
</resource-ref>
[...]
spring-jpa-config.xml
<jpa:repositories base-package="whatever.core.repositories" />
<jee:jndi-lookup id="dataSource" jndi-name="EngineDS" cache="true" resource-ref="true" expected-type="javax.sql.DataSource"/>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="whatever.core.entities" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="${hibernate.show_sql}" />
<property name="generateDdl" value="${jpa.generateDdl}" />
<property name="databasePlatform" value="${jpa.dialect}" />
</bean>
</property>
</bean>
<tx:annotation-driven />
<tx:jta-transaction-manager />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<bean class="org.springframework.orm.hibernate4.HibernateExceptionTranslator"/>
We had made in the past jboss AS5/Spring 3.0 applications to work with JTA transactions, so it is not like is my first time doing this, and we've been looking around all possible blogs and open source projects I could find. Yet anything that seem to work smoothly to everybody seems to be ignored in my application. I'm sure it should be that we're missing something really stupid somewhere but we've tried so far 70+ different configurations and none seem do a simple insert that otherwise work when not trying JTA.
(The fact that we use axis 1.4 might be relevant or not, but I'd like to tell because our application only triggers actions after a web service call). At this point we are starting to believe in configuration paranormal activity...
Any clue anyone?

It turned out that the configuration above wasn't working due to the fact that I was using org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.
To have JTA I should lookup for the JBoss container-managed entity manager spring-jpa.config.xml:
<!-- lookup the container-managed JPA-EMF -->
<!-- the JNDI name is specified in META-INF/persistence.xml -->
<!-- SEE: https://docs.jboss.org/author/display/AS71/JPA+Reference+Guide#JPAReferenceGuide-BindingEntityManagerFactorytoJNDI -->
<jee:jndi-lookup id="defaultPu" jndi-name="java:jboss/defaultPu" />
And in the META-INF/persistence.xml you bind the Entity Manager Factory into JNDI:
<!-- bind the EMF in JNDI -->
<property name="jboss.entity.manager.factory.jndi.name" value="java:jboss/defaultPu" />
So, I let Jboss bootstrap JPA, and in such way the JTA transactions work!

Related

JPA connects to a different database instead of the one specified in my persistence.xml

Here's my persistence xml file
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="GoodreadsJpa">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>entity.Book</class>
<class>entity.Review</class>
<class>entity.UserActionLog</class>
<class>entity.User</class>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/goodreads_clone?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC;" />
<property name="eclipselink.jdbc" value="jdbc:mysql://localhost:3306/goodreads_clone?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC;"/>
<property name="javax.persistence.jdbc.user" value="root" />
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
</properties>
</persistence-unit>
As you can see I have provided jdbc url for connecting to the database. However, when I run my application I get the following information.
14:31:57,377 INFO [org.eclipse.persistence.connection] (default task-2) Connected: jdbc:h2:mem:test
User: ROOT
Database: H2 Version: 1.3.173 (2013-07-28)
Driver: H2 JDBC Driver Version: 1.3.173 (2013-07-28)
which states that I connected to jdbc:h2:mem:test and consequently I cannot perform the desired actions.
It makes me think I am connected to a wrong database?Am I missing something? How can I actually connect to the db that I want?
I am using Wildfly 10 and EclipseLink. Not using Maven.
Assuming you're using container-managed em, you should define your data source in Wildfly configuration (standalone.xml). You should then refer to your datasource using the persistence-unit.jta-data-source (or persistence-unit.non-jta-data-source) tag in your persistence unit definition.
If you need both the MySQL and H2 data sources, you can create multiple persistence units and differentiate between them using #PersistenceContext(name = "...")
1.You need to add mysql driver to Jboss like here : Can't add mysql driver to jboss
or here
https://synaptiklabs.com/posts/adding-the-mysql-jdbc-driver-into-wildfly/
You need add mysql datasource in standalone.xml configuration file like here :
https://zorq.net/b/2011/07/12/adding-a-mysql-datasource-to-jboss-as-7/
<datasource jndi-name="java:/mydb" pool-name="my_pool" enabled="true" jta="true" use-java-context="true" use-ccm="true">
<connection-url>jdbc:mysql://localhost:3306/mydb</connection-url>
<driver>mysql</driver>
<security>
<user-name>root</user-name>
<password>root</password>
</security>
<statement>
<prepared-statement-cache-size>100</prepared-statement-cache-size>
<share-prepared-statements />
</statement>
</datasource>

safety disconnect oracle db from a jboss application

I'm maintenance a old system it run in a jboss container,and it use ibatis and spring access an oracle db. Now this system's db related functions are discarded and the db will be closed. How should i do to safety disconnect this system with db (assuming the application code can deal with all exceptions except SqlException)
the key configuration is as follows:
xxx-ds.xml:
<datasources>
...
</datasources>
daoContext.xml:
<jee:jndi-lookup id="oracleSource" jndi-name="java:/DefaultDS"/>
<!-- SqlMap setup for iBATIS Database Layer -->
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="META-INF/sql-map-config.xml"/>
</bean>
<bean id="xxxx" class="path.to.class.xxxxDao">
<property name="dataSource" ref="oracleSource"/>
<property name="sqlMapClient" ref="sqlMapClient"/>
</bean>
path.to.class.xxxxDao is extends org.springframework.orm.ibatis.support.SqlMapClientDaoSupport and implements db access methods.
Replace jndi data source with a mock db

Configuring database connection in Jboss FUSE

One way I know to configure DB in JBOSS FUSE is to use blueprint.xml.
Below configuration in blueprint.xml works
<bean id="gemsDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="${gems_url}" />
<property name="username" value="${gems_username}" />
<property name="password" value="${gems_password}" />
<property name="maxIdle" value="5" />
<property name="minIdle" value="1" />
<property name="initialSize" value="1" />
</bean>
However, Is there any way to configure it in JBOSS container specific configuration file. For example - In JBOSS EAP we can configure it in standalone.xml. On similar lines can we configure it in JBOSS FUSE?
Jboss Fuse provides the integration with various data sources. You need to configure them bundle wise like you have used. But no such configuration is there on container level.
You can define a Datasource in a bundle and export it. In other bundles you import and use it like a service.
Prerequisites
Install these features
features:install jdbc
features:install jndi
Datasource bundle
Drop an XML file inside deploy folder with following content:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<bean id="dataSource" class="org.postgresql.jdbc3.Jdbc3SimpleDataSource">
<property name="url" value="jdbc:postgresql://localhost:5432/databasename"/>
<property name="user" value="username"/>
<property name="password" value="xxx"/>
</bean>
<service interface="javax.sql.DataSource" ref="dataSource">
<service-properties>
<entry key="osgi.jndi.service.name" value="jdbc/yourdatabasename_ds"/>
</service-properties>
</service>
</blueprint>
This will export a service with javax.sql.DataSource interface and a JNDI name
Use Datasource service
When a bundle needs the datasource, ask OSGi to inject it.
<blueprint>
<reference id="yourDatabaseDs"
interface="javax.sql.DataSource"
availability="mandatory"
filter="(osgi.jndi.service.name=jdbc/yourdatabasename_ds)"/>
</blueprint>
The right Datasource is retrieved using the JNDI name you provided.
Using availability="mandatory" you can force your bundle to wait for the Datasource to become available. The bundle won't start without this reference.
You need the correct JDBC drivers for the database you are using.
Other goodies
You have a lot of commands in JBoss Fuse console to interact with the database now, like jdbc:datasources that will list all available datasources. With jdbc:query you can run any SQL against your DB (good for debugging issues and testing the connection)

Illogical Results from Cucumer/Arquillian Test with H2

I am having an issue where I am attempting to create a Cucumber/Arquillian test for a new service that performs a batch update with JPQL. Everything seems to work correctly, except my #Then code validating the change.
I am setting up my test data in my feature file and it gets added to the H2 database that is created in memory for each test. When the batch update runs it reports back the expected update count based on that data. But when I retrieve one of the objects that should have been updated, the data on that object appears to be unchanged.
Please note: When I execute the service call in my application against our Oracle database it works correctly and the table is updated as expected. The problem seems to be with caching on the H2 in memory database.
My datasource that gets deployed to JBoss by Arquillian is:
<datasource enabled="true"
jndi-name="jdbc/arquillian"
pool-name="ArquillianEmbeddedH2Pool">
<connection-url>
jdbc:h2:mem:arquillian;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS TEST_DB
</connection-url>
<driver>h2</driver>
</datasource>
My Cucumber test defines #PersistenceContext(unitName = "localH2-testDB")
My persistence.xml contains:
<persistence-unit name="localH2-testDB">
<jta-data-source>jdbc/arquillian</jta-data-source>
<properties>
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.cache.use_second_level_cache" value="false"/>
<property name="hibernate.cache.use_query_cache" value="false"/>
</properties>
</persistence-unit>
I don't know what other settings for the H2 database I can change to try and eliminate any caching.
It turns out the problem is inherent to how batch updates are handled in JPA. They do NOT update the persistence cache as one might expect. So the tables were updated correctly, but when the object was re-queried, it didn't have the updates. This is why my test was failing (everything was inside the same transaction) and my deployed code worked (separate transactions performing the update and re-querying the data).

Mybatis caching and concurrent modfications

I am using mybatis 3.0.4 for a test against a mysql 5.5 database with mysql-connector JDBC driver, version 5.1.16.
The problem I am experiencing is that if I get a SqlSession via openSession() method and i retrieve data via a select from database, subsequent selects in same session are not aware of changes made (and committed) to database even if i call clearCache() on session. To concurrently modify database I am using Mysql command line client. Setting cacheEnabled as false in configuration file doesn't help too.
I enclose configuration file.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//ibatis.apache.org//DTD Config 3.0//EN"
"http://ibatis.apache.org/dtd/ibatis-3-config.dtd">
<configuration>
<settings>
<setting name="lazyLoadingEnabled" value="false"/>
<setting name="cacheEnabled" value="false"/>
</settings>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="poolMaximumIdleConnections" value="20"></property>
<property name="poolMaximumActiveConnections" value="80"></property>
<property name="poolMaximumCheckoutTime" value="600"></property>
<property name="poolTimeToWait" value="600"></property>
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/testdb"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mappers/TestMapper.xml" />
</mappers>
</configuration>
Ok, solved by myself. It was not a mybatis issue, it depended on Transaction isolation on JDBC driver, which was by default TRANSACTION_REPEATABLE_READ, I needed TRANSACTION_READ_COMMITTED instead. Solved with:
getSessionFactory().openSession(TransactionIsolationLevel.READ_COMMITTED);