Failing to connect to database some times spring-jdbc, commons-dbcp,tomcat - spring

I am using spring3 and org.apache.commons.dbcp.BasicDataSource and apache tomcat 6.x.
Once the application is started it works fine but after some time it fails to connect to database... on restart it connects again.
below is configuration used in applicationContect.xml
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:initialSize="5" p:maxActive="15" p:maxIdle="5" p:driverClassName="com.mysql.jdbc.Driver" p:url="jdbc:mysql://<Host>/<schema>?useUnicode=true&" p:username="<uName>" p:password="<pwd>" p:testOnBorrow="true" p:validationQuery="SELECT 1"/>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
Can there be any problem with the configuration?
Also, i am not closing/handling jdbc connections/resultset and i assume spring-jdbc will take care of it .
I am getting the below exception:
org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, general error

executing stored procedures with jdbcTemplate.query was failing some times.
Instead i used org.springframework.jdbc.core.simple.SimpleJdbcCall for calling stored procedures and its working fine

Related

Handle Spring data source being temporarily unavailable during Hibernate initialisation

Part of my Spring (4.3.23) / Hibernate (5.0.12) application "A" uses a data source that is exposed be a second application "B" (the data source is an in-memory database). Both A and B are deployed in Tomcat and I don't control start order. Once both A and B have started both behave as expected, however if A starts before B an error is thrown during initialisation when Hibernate tries to query the data source:
org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator - HHH000342: Could not obtain connection to query metadata : Cannot create PoolableConnectionFactory (Connection is broken: "java.net.ConnectException: Connection refused: 127.0.1.1:5521" [90067-199])
Is there any way I can suppress this error, delay this part of initialisation, or tell Hibernate that the data source may not be immediately available?
Here are the relevant parts of my configuration:
<bean id="memDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/memdb" />
</bean>
<bean
id="memSessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="memDataSource" />
<property name="packagesToScan" value="com.company" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
</props>
</property>
</bean>
<bean id="memTransactionManager"class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="memSessionFactory" />
<qualifier value="memTransactions"/>
</bean>
<tx:annotation-driven transaction-manager="memTransactionManager" />
I would wind up scripting the deployment overall. Bring up tomcat with application A in the webapps directory, and periodically ping for successful deployment of application A before copying/moving over application B into the webapps directory for deployment.
This entire solution would likely work best if you used a staging directory to move your war files onto that server, and then let the script clear the webapps directory and move/copy the new war(s) into webapps for fresh deployment.
SideNote: I've found that deployment of applications seems to be in a constant order, but I'm not sure as it is alphabetical, oldest first, or something else.

Spring WorkManagerTaskExecutor cannot initialize in websphere

i want use Websphere work manager for executing async jobs in jee context but i have problem with creating spring WorkManager.
bean definition:
<bean id="taskExecutor" class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor"> <property name="workManagerName" value="wm/default" /> </bean>
this definition i found in websphere help. But problem is this ends with noClassDefFound. I noticed pckg org.springframework.scheduling.commonj is missing from spring-context since version 2.x.x
Is it replaced with org.springframework.jca.work.WorkManagerTaskExecutor ?
when i use this other spring class, i get error:
Caused by: org.springframework.jndi.TypeMismatchNamingException:
Object of type [class com.ibm.ws.asynchbeans.WorkManagerImpl]
available at JNDI location [wm/default] is not assignable to
[javax.resource.spi.work.WorkManager]
so whats deal here? thx
was - 7.0.0.23
spring - 3.1.2
Class org.springframework.scheduling.commonj.WorkManagerTaskExecutor resides in spring-context-support-3.1.2.RELEASE.jar
Configuration succeeds with javax.resource.spi.work.WorkManager in applicationContext-service.xml in deployment.....
In my case deployment fails for bean injection org.springframework.scheduling.commonj.WorkManagerTaskExecutor as it fails to take WorkManager JNDI Configured in Application Server.... I just replaced javax.resource.spi.work.WorkManager. And so far it is success deployment.
I yet to see application works fine with it.
<bean id="taskExecutor" class="javax.resource.spi.work.WorkManager">
<property name="workManagerName" value="wm/default" />
</bean>
In our scenario we were managed it by ThreadPoolTaskExecutor instead of WorkManagerTaskExecutor
Here is configuration that comes in ApplicationContext.xml
<!--
<bean id="rtSenderTaskExecutor"
class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor">
<property name="workManagerName">
<value>${org.quartz.threadPool.jndi}</value>
</property>
</bean> -->
<!-- Local Thread Pool -->
<bean id="rtSenderTaskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="${org.quartz.threadPool.corePoolSize}" />
<property name="maxPoolSize" value="${org.quartz.threadPool.maxPoolSize}" />
<property name="queueCapacity" value="${org.quartz.threadPool.queueCapacity}" />
<property name="keepAliveSeconds" value="${org.quartz.threadPool.keepAliveSeconds}"></property>
</bean>

BoneCP sometimes cannot get config from spring property holder

I have been facing this issue for a while now. My config is as following
<!-- Load Properties Files -->
<context:property-placeholder location="classpath:*-${environment}.properties" ignore-unresolvable="true"/>
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="idleConnectionTestPeriodInMinutes" value="${boneCP.idleConnectionTestPeriodInMinutes}"/>
<property name="idleMaxAgeInMinutes" value="${boneCP.idleMaxAgeInMinutes}"/>
<property name="maxConnectionsPerPartition" value="${boneCP.maxConnectionsPerPartition}"/>
<property name="minConnectionsPerPartition" value="${boneCP.minConnectionsPerPartition}"/>
<property name="partitionCount" value="${boneCP.partitionCount}"/>
<property name="acquireIncrement" value="${boneCP.acquireIncrement}"/>
<property name="statementsCacheSize" value="${boneCP.statementsCacheSize}"/>
<property name="lazyInit" value="true"/>
<property name="maxConnectionAgeInSeconds" value="${boneCP.maxConnectionAgeInSeconds}"/>
</bean>
The project is running on Tomcat 7
On the local machine, the project deploy with no error as well as for the dev server. Unfortunately, the project cannot be deployed on dev server any more (server configuration remain same) while local machine is still fine. Every time I deploy the project on the dev server, Tomcat just hang at INFO: Deploying web application archive /etc/tomcat/webapps/project.war. But if I config BoneCP with real values, everything is fine.
Could any one tell me what's wrong with it?
It turned out to be the lazyInit problem. If I comment it out, the server can start normally. But now I'm facing the new issue though. Mybatis cannot access the db at all while the local machine is 100% fine. and yet dont throw any exception. But when I stop the server, I found the following exceptions
INFO: Illegal access: this web application instance has been stopped already. Could not load com.jolbox.bonecp.PoolUtil. The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.
java.lang.IllegalStateException
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1600)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
at com.jolbox.bonecp.DefaultConnectionStrategy.getConnectionInternal(DefaultConnectionStrategy.java:94)
at com.jolbox.bonecp.AbstractConnectionStrategy.getConnection(AbstractConnectionStrategy.java:90)
at com.jolbox.bonecp.BoneCP.getConnection(BoneCP.java:540)
at com.jolbox.bonecp.BoneCPDataSource.getConnection(BoneCPDataSource.java:131)
at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111)
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)
at org.mybatis.spring.transaction.SpringManagedTransaction.openConnection(SpringManagedTransaction.java:80)
at org.mybatis.spring.transaction.SpringManagedTransaction.getConnection(SpringManagedTransaction.java:66)
AND
INFO: Illegal access: this web application instance has been stopped already. Could not load org.apache.ibatis.reflection.ExceptionUtil. The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.
java.lang.IllegalStateException
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1600)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:363)
at sun.proxy.$Proxy15.selectList(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:195)
at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:124)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:90)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:40)
at sun.proxy.$Proxy45.selectByExample(Unknown Source)
Well it could be many things but its most likely
properties are not being replaced with the values you think
the database number of connections has been exceeded or the wrong host
A combination of 1 + 2
For #1 I would a make a separate bean that needs com.jolbox.bonecp.BoneCPDataSource as a dependency and have it print out the getters of BoneCPDataSource.
For #2 I would turn on as much logging as possible (see log4j or logback or whatever your logging framework is).

Spring JNDI datasource not recognized after upgrade to ActiveMQ 5.6.0

I tested a ActiveMQ 5.5.0 (fuse version) app in AMQ 5.6.0 and noticed that our Spring JNDI configured Oracle datasources aren't being found.
The only thing I changed in my applications was the pom.xml versions of AMQ/Spring (to match the 5.6 versions). Otherwise, I'm using the identical application code and configuration (activemq.xml, jndi.xml, etc), but my Spring JDBC DAOs (v3.0.5) are failing to find them.
No errors in the logs otherwise, just this Spring Application Context initialization error...
javax.naming.NameNotFoundException; remaining name 'jdbc/myDataSource'
here is the relevant Spring jndi config (conf/jndi.xml, included in conf/activemq.xml)...
<bean id="jndi" class="org.apache.xbean.spring.jndi.SpringInitialContextFactory"
factory-method="makeInitialContext" scope="singleton">
<property name="entries" ref="jndiEntries" />
</bean>
<util:map id="jndiEntries">
<entry key="jdbc/myDataSource">
<bean id="myDBCPDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.OracleDriver" />
...
then my application references it like this...
<bean id="myDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>jdbc/myDataSource</value>
</property>
</bean>
<bean id="messageDAO" class="com.mycompany.MessageDAOImpl">
<property name="dataSource" ref="myDataSource" />
</bean>
That said, I tested without using JNDI (instead just hardcoded the datasource in my app) and everything works as expected. So that should rule out everything except the Spring JNDI registration/lookup of the datasource, etc.
So, what am I missing?
ActiveMQ has a dependency into xbean-spring, which you are using as a JNDI provider. It is likely that the transitive Xbean dependency has changed because of the upgrade to ActiveMQ 5.6.0.
I found the issue, I added a jndi.properties file under the /conf directory containing the following and it works fine now (didn't need this under AMQ 5.5...strange)...
java.naming.factory.initial = org.apache.xbean.spring.jndi.SpringInitialContextFactory

Start the H2 database in server mode via Spring

I'm trying to start the H2 database in server mode (I want it to run in a different process) via Spring.
Currently I'm using java Runnable.exec to start the h2 database (using the command: "java -cp h2.jar org.h2.tools.Server")
I know that there is a way to do it via Spring. I tried to add the following to the spring configuration, but it didn't work (it didn't start the H2 database):
<bean id="org.h2.tools.Server" class="org.h2.tools.Server"
factory-method="createTcpServer" init-method="start" destroy-method="stop">
<constructor-arg value="-tcp,-tcpAllowOthers,true,-tcpPort,8043" />
</bean>
<bean id="org.h2.tools.Server-WebServer" class="org.h2.tools.Server"
factory-method="createWebServer" init-method="start">
<constructor-arg value="-web,-webAllowOthers,true,-webPort,8082" />
</bean>
I would appreciate any help/ideas
Do you happen to have:
<beans default-lazy-init="true" ...
in your Spring configuration files?
Recently I had to do the same configuration to make unit test and check data, this works for me (Spring 3.1.4). Then you just have to connect with jdbc:h2:tcp://localhost:8043/mem:test and make sure to put a while(true){} at the end of your test.
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.h2.Driver"/>
<!--property name="url" value="jdbc:h2:mem:;TRACE_LEVEL_FIlE=4"/-->
<property name="url" value="jdbc:h2:mem:test;DB_CLOSE_DELAY=-1"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean class="org.h2.tools.Server" factory-method="createTcpServer" init-method="start" destroy-method="stop">
<constructor-arg>
<array>
<value>-tcp</value>
<value>-tcpAllowOthers</value>
<value>-tcpPort</value>
<value>8043</value>
</array>
</constructor-arg>
</bean>
Are you sure the createTcpServer method in the Server class is really called? Have you tried setting up a breakpoint there?
H2 tutorial claims this how you can create and start the server programmatically:
import org.h2.tools.Server;
...
// start the TCP Server
Server server = Server.createTcpServer(args).start();
...
// stop the TCP Server
server.stop();
Your Spring definition seems to mimick the same initialization. But you can always try doing it manually - maybe it's some fault in Spring configuration.
EDIT:
I've tried your configuration and it works for me. What makes you think the server is not started? It doesn't print out anything on stdout, however the process listens at the 8043 port. So it seems pretty OK.

Resources