safety disconnect oracle db from a jboss application - jboss

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

Related

StrategySelectionException using HikariCP with hibernate

I am new to hibernate, and I have been tasked with changing the ConnectionProvider from the hibernate default CP to either Hikari (preferred) or C3P0 in a legacy Java application that does not use maven as a repository. The database is PostgreSQL. The hibernate version is hibernate-release-5.2.10.Final. I have added hibernate-hikaricp-5.2.10.Final.jar to the classpath.
I have a pre-existing xml configuration file for hibernate. This has been working for several years, but the project wants to change to a "production ready connection pool". I have added/modified properties for the connection provider as follows:
<property name="hibernate.connection.provider_class">org.hibernate.hikaricp.internal.HikariCPConnectionProvider</property>
<property name="hibernate.hikari.minimumIdle">5</property>
<property name="hibernate.hikari.maximumPoolSize">20</property>
<property name="hibernate.hikari.idleTimeout">30000</property>
I am getting the following StrategySelectionException (long stack trace reduced to exceptions/causes ... more information available if necessary).
Exception in thread "DatabaseCache initialize thread" org.hibernate.service.spi.ServiceException: Unable to
create requested service [org.hibernate.engine.jdbc.connections.spi.ConnectionProvider]
...
Caused by: org.hibernate.boot.registry.selector.spi.StrategySelectionException: Unable to resolve name [org.hibernate.hikaricp.internal.HikariCPConnectionProvider] as strategy [org.hibernate.engine.jdbc.connections.spi.ConnectionProvider]
I made one other change, after first seeing the exception. I added the following property, but it made no difference.
<property name="hibernate.implicit_naming_strategy">default</property>
The full configuration, with some information provided as variables replaced during build, is:
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="hibernate.implicit_naming_strategy">default</property>
<property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
<property name="hibernate.connection.provider_class">org.hibernate.hikaricp.internal.HikariCPConnectionProvider</property>
<property name="hibernate.hikari.minimumIdle">5</property>
<property name="hibernate.hikari.maximumPoolSize">20</property>
<property name="hibernate.hikari.idleTimeout">30000</property>
<property name="hibernate.connection.username">${db_user_name}</property>
<property name="hibernate.connection.password"></property>
<property name="hibernate.connection.url">${db_connection_url}</property>
<property name="hibernate.hbm2ddl.auto">none</property>
<property name="hibernate.connection.autocommit">false</property>
<property name="hibernate.bytecode.use_reflection_optimizer">false</property>
<property name="hibernate.jdbc.time_zone">GMT</property>
<property name="hibernate.generate_statistics">false</property> <!-- This affects performance, use only in development -->
<property name="show_sql">false</property>
</session-factory>
</hibernate-configuration>
Any strategies :D to address this would be welcome. Thanks.

Configure Spring batch admin to use db2 database

In order to configure spring batch admin UI to use db2 database, I referred the Admin UI documentation which says "launch the application with a system property -DENVIRONMENT=[type]." I understand that "-DENVIRONMENT=db2" should be kept in some file. I tried by keeping in batch-default.properties file, but that did not work. Since I am using WLP(liberty server), tried by keeping in server.xml file, no help. Still in the console I see env-context.xml file from batch admin is still loading batch-hsql.properties file(default configuration).
My job is written using Spring Boot so I put property, ENVIRONMENT=db2 in application.properties and add a new file - batch-db2.properties at same location as application.properties.
Few compulsory properties will be needed there like - you need to try an experiment,
batch.job.configuration.package=
batch.drop.script=classpath*:/org/springframework/batch/core/schema-drop-db2.sql
batch.schema.script=
batch.business.schema.script=
#Copied from batch.properties of spring-batch-admin-manager API project
batch.jdbc.testWhileIdle=false
batch.jdbc.validationQuery=
batch.data.source.init=false
batch.job.configuration.file.dir=target/config
batch.job.service.reaper.interval=60000
batch.files.upload-dir=/sba/input
I had put DB connection information too but later I moved to JNDI by overriding file - data-source-context.xml in META-INF\spring\batch\override like below,
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="ConnectionPool" />
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
ConnectionPool is db connection pool JNDI name from server.
Keeping configurations in your code lets you freely move your app to different servers without asking for server specific configurations first.
Not really familiar with liberty server, but the link below says that system properties need to be added to jvm.options file. See link below :
https://www.ibm.com/support/knowledgecenter/en/SSEQTP_liberty/com.ibm.websphere.wlp.doc/ae/twlp_admin_customvars.html

propagation NOT_SUPPORTED creates failing transaction in JDBC when using ChainedTransactionManager (JDBC + JPA)

I'm working on an existing Spring application that uses JDBC (DAO's extend NamedParameterJdbcDaoSupport). There were four datasources configured, each with it's own DataSourceTransactionManager. (though only one was registered with tx:annotation-driven for some reason)
I've recently added JPA (Spring-data-JPA) into the application and configured two entityManagerFactories (for now I don't need the other two datasources). I also configured two JpaTransactionManagers and removed the corresponding DataSourceTransactionManagers for these dataSources, since the JpaTransactionManagers can also be used for JDBC transactions. (correct me if I'm wrong)
It appears I need to be able to have distributed transactions, since the two datasources (to two different databases) need to be accessed (through JPA) in one service method. Since I did not have all I need to set up JTA (missing XA-driver for one of the databases) I've decided to give the Spring ChainedTransactionManager a try. Sadly this didn't work out as expected. All works fine if I just call a service method that only uses JPA.
Though when I call an existing service method that uses a JDBC find that has a class level #transactional annotation with it's propagation set to NOT_SUPPORTED and call another service method after that with a JPA call and a #transactional, I get an exception:
Caused by: java.lang.IllegalStateException: Already value [org.springframework.jdbc.datasource.ConnectionHolder#462cf9d9] for key [org.jboss.jca.adapters.jdbc.WrapperDataSource#3fbb4c32] bound to thread [http-/127.0.0.1:8080-5]
at org.springframework.transaction.support.TransactionSynchronizationManager.bindResource(TransactionSynchronizationManager.java:189) [spring-tx-3.2.5.RELEASE.jar:3.2.5.RELEASE]
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:403) [spring-orm-3.2.5.RELEASE.jar:3.2.5.RELEASE]
After some debugging, I found out that the transactions in Spring get added to a map on a ThreadLocal in the "TransactionSynchronizationManager.bindResource" method. The problem is that when using a JDBC call with #transactional and propogation NOT_SUPPORTED, a transaction is made anyway and registered through that method. When the JpaTransactionManager tries to bind it's resource, it is already on the map (and not marked as void) which causes the error to occur.
Changing the propagation to the default "REQUIRED" for the service call that encapsulates the JDBC call fixes the problem.
I have no idea why Spring is still creating that transaction when the transactional annotation is NOT_SUPPORTED. And if it creates that transaction, it should not bypass the JpaTransactionManager.
So what I'd like to know is if there is some way to tell Spring to use the JpaTransactionManager also when it creates a transaction itself inside the NamedParameterJdbcDaoSupport. (Well actually the JdbcDaoSupport... Well actually the DataSourceUtils)
We're using Spring 3.2.5, spring-data-jpa 1.6.0 and I've used Hibernate 4.2.0 as JpaVendor.
This problem doesn't occur without the ChainedTransactionManager.
Datasources:
<bean id="dataSourceCompta" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:jboss/datasources/comptaDS"/>
</bean>
<bean id="dataSourceUnisys" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:jboss/datasources/insoverDS"/>
</bean>
<bean id="dataSourceInsoverwebMysql" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:jboss/datasources/insoverWebDS"/>
</bean>
<bean id="dataSourceBatch" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:jboss/datasources/batchDS"/>
</bean>
Single remaining JDBC transaction manager (no JPA counterpart):
<bean id="transactionManagerBatch" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSourceBatch"/>
</bean>
JPA Transaction Managers:
<bean id="jpaUnisysTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryUnisys"/>
<qualifier value="unisys" />
</bean>
<bean id="jpaMysqlTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryMysql"/>
<qualifier value="mysql" />
</bean>
My ChainedTransactionManager:
<bean id="chainedTransactionManager" class="org.springframework.data.transaction.ChainedTransactionManager">
<constructor-arg>
<list>
<ref bean="jpaUnisysTransactionManager" />
<ref bean="jpaMysqlTransactionManager" />
</list>
</constructor-arg>
</bean>
JPA Entity manager factories:
<bean name="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
<bean id="entityManagerFactoryUnisys" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:META-INF/some-persistence.xml"/>
<property name="dataSource" ref="dataSourceUnisys"/>
<property name="persistenceUnitName" value="unisysPU"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<property name="jpaProperties">
<!-- properties -->
</property>
</bean>
<bean id="entityManagerFactoryMysql" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:META-INF/some-persistence.xml"/>
<property name="dataSource" ref="dataSourceCompta"/>
<property name="persistenceUnitName" value="mysqlPU"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<property name="jpaProperties">
<!-- properties -->
</property>
</bean>
For now I've "fixed" this, by changing all the class-level transactional annotations to have propagation.REQUIRED (default) instead of NOT_SUPPORTED. Though I do not really like this solutions, since it might be somebody set those propagations to NOT_SUPPORTED with a good reason. I've also tried SUPPORTED, but using that had the same issue as NOT_SUPPORTED: a transaction was being made anyway by the Spring DataSourceUtils when the query was being executed by the NamedParameterJdbcDaoSupport DAO.
When no transactional annotation is set on the service, all works well too.

OrientDB - JDBC Driver controlled by a Connection Pool

We are in the process of changing some of the applications that use a relation database, to OrientDB (2.1.9).
This transaction will be made in small steps, we will first start with the JDBC driver approach, and maybe we will switch to a native implementation later.
We have an application that is based on Spring Integration, where we changed from an Oracle Database to OrientDB, using the JDBC driver.
The database connections are managed by Tomcat 8 Connection Pool, and the transactional behavior is handled by Spring's Transaction Manager:
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close">
<property name="driverClassName" value="com.orientechnologies.orient.jdbc.OrientJdbcDriver" />
...
</bean>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
After changing the database to OrientDB, we encountered the following error:
com.orientechnologies.orient.core.exception.ODatabaseException: Database instance is not set in current thread. Assure to set it with: ODatabaseRecordThreadLocal.INSTANCE.set(db);
The OrientDB documentation, on Multi threading, states:
OrientDB supports multi-threads access to the database. ODatabase* and OrientGraph* instances are not thread-safe, so you've to get an instance per thread and each database instance can be used only in one thread per time. For more information about how concurrency is managed by OrientDB look at Concurrency.
Since v2.1 OrientDB doesn't allow implicit usage of multiple database instances from the same thread. Any attempt to manage multiple instances in the same thread must explicitly call the method db.activateOnCurrentThread() against the database instance BFORE you use it.
This posed a problem, as all the database connection management is handled by the connection pool (as it should be).
So, in order to implement the solution proposed by OrientDB, I had to have access to the underlying ODatabaseDocumentTx database, in order to apply the activateOnCurrentThread() method.
To be able to do it, I had to create a wrapper from both the JDBC driver class, and the OrientJdbcConnection.
In the OrientJdbcConnection, I obtained the underlying database by the use of Java Reflection:
public class OrientJdbcConnectionWrapper extends OrientJdbcConnection {
#Override
public void commit() throws SQLException {
final ODatabaseDocumentTx database = getPrivateDatabaseFieldByReflection();
database.activateOnCurrentThread();
super.commit();
}
And the JDBC Driver class wrapper, now returns a wrapped connection:
public class OrientJdbcDriverWrapper extends OrientJdbcDriver {
public Connection connect(final String url, final Properties info) throws SQLException {
if (!acceptsURL(url)) {
throw new SQLException(DO_NOT_ACCEPT_URL_ERROR + url);
}
return new OrientJdbcConnectionWrapper(url, info);
}
}
Finally, the configuration of the Connection pool now uses the wrapped driver:
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close">
<property name="driverClassName" value="x.y.z.driver.orientdb.OrientJdbcDriverWrapper" />
</bean>
As expected, this works perfectly, but i'm not entirely sure that this is the correct way to do it as i haven't see anyone with this issue.
On the other hand, the OrientDB documentation does suggest the use of activateOnCurrentThread() on a multi-threading environment.
OrientDB has its own database pool, that can be easily configured:
<bean id="dataSource" class="com.orientechnologies.orient.jdbc.OrientDataSource">
<constructor-arg name="url" value="jdbc:orient:plocal:xx\\databases\\test" />
<constructor-arg name="username" value="xx"/>
<constructor-arg name="password" value="xx"/>
<constructor-arg name="info" ref="databaseProperties" />
</bean>
<util:map id="databaseProperties" value-type="java.lang.String">
<entry key="db.usePool" value="true" />
<entry key="db.pool.min" value="1" />
<entry key="db.pool.max" value="10" />
Note: I'm using OrientDB through its orient-jdbc driver.

Error for Oracle Driver for DB server 10g and Jboss 4.2.3 application server

the error is like
Apparently wrong driver class specified for URL: class: oracle.jdbc.driver.OracleDriver
I am using ojdbc14.jar which is the latest jar for oracle driver. The DB server is Oracle 10g. I am using spring framework and refereing the jndi name defined in oracle-ds under jboss installation directory.
I dont know why this error is coming.
kindly help me to resolve this issue
I face same problem. In my case I can work it out by changing the Replace JNDI data source with Apache Data Source. I am not sure this will work on your environtment. Somehow the spring JNDI could not pick up the JDBC driver class. My database is an Informix database. I hope it helped.
JNDI version:
<bean id="lmsDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/smsifmx</value>
</property>
</bean>
Apache Data Source version:
<bean id="lmsDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="url">
<value>jdbc:informix-sqli://<ip_to_your_db>:<db_port>/<server_name>:INFORMIXSERVER=<db_name></value>
</property>
<property name="driverClassName">
<value>com.informix.jdbc.IfxDriver</value>
</property>
<property name="username">
<value><db_user></value>
</property>
<property name="password">
<value><db_password></value>
</property>
</bean>