Invoking flyway via spring's depends-on attribute causes infinite loop - java

I'm using flyway via spring. In my xml context file I have some bean definitions as follows:
<bean id="baseVersion" class="org.flywaydb.core.api.MigrationVersion">
<constructor-arg index="0" value="${flyway.baseVersion}"/>
</bean>
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
<property name="driverClass" value="${database.driverClassName}"/>
<property name="jdbcUrl" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</bean>
<bean id="flyway" class="org.flywaydb.core.Flyway" init-method="migrate" >
<property name="dataSource" ref="dataSource"/>
<property name="baselineVersion" ref="baseVersion"/>
<property name="baselineOnMigrate" value="${flyway.baselineOnMigrate}"/>
<property name="validateOnMigrate" value="${flyway.validateOnMigrate}"/>
<property name="ignoreFutureMigrations" value="${flyway.ignoreFutureMigrations}"/>
<property name="ignoreMissingMigrations" value="${flyway.ignoreMissingMigrations}"/>
<property name="outOfOrder" value="${flyway.outOfOrder}"/>
<property name="targetAsString" value="${flyway.targetVersion}"/>
</bean>
<!-- *************************************************************** -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" depends-on="flyway">
<property name="annotatedClasses" >
<list>
<value>foo.bar.Entity1</value>
...
</list>
</property>
<property name="dataSource" ref="dataSource"/>
<property name="mappingResources">
<list>
<value>/hbms/Table1.hbm.xml</value>
....
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${database.dialect}</prop>
...
</props>
</property>
</bean>
The problem is that when flyway fails on migration, spring swallows its exception and retries to invoke it again and again ... and falls on an infinite loop!
2017-11-21 10:07:35,280 [main] INFO o.f.c.i.dbsupport.DbSupportFactory - Database: jdbc:oracle:thin:#192.168.99.100:1521:orcl (Oracle 11.2)
2017-11-21 10:07:37,564 [main] INFO o.f.c.i.dbsupport.DbSupportFactory - Database: jdbc:oracle:thin:#192.168.99.100:1521:orcl (Oracle 11.2)
2017-11-21 10:07:38,884 [main] INFO o.f.c.i.dbsupport.DbSupportFactory - Database: jdbc:oracle:thin:#192.168.99.100:1521:orcl (Oracle 11.2)
2017-11-21 10:07:39,565 [main] INFO o.f.c.i.dbsupport.DbSupportFactory - Database: jdbc:oracle:thin:#192.168.99.100:1521:orcl (Oracle 11.2)
2017-11-21 10:07:40,214 [main] INFO o.f.c.i.dbsupport.DbSupportFactory - Database: jdbc:oracle:thin:#192.168.99.100:1521:orcl (Oracle 11.2)
...
One consequence of this problem is that Oracle locks the user when password is wrong, because the FAILED_LOGIN_ATTEMPTS exceeds from LIMIT value when it's not UNLIMITED!
I've traced the code of spring ... the exception is catched at line 1760 of AbstractAutowireCapableBeanFactory class and goes forward ... and finally somehow suppressed despite the recordSuppressedExceptions is false in DefaultSingletonBeanRegistry class!
The spring-beans version is 4.3.11 and the version of flyway is 4.2.0.
Any solution or workaround?
p.s. Spring prints the flyway's exception just when I increase the level of log to TRACE.
UPDATE
Flyway's properties:
#database migration config
flyway.baseVersion=1.0
flyway.baselineOnMigrate=true
flyway.validateOnMigrate=true
flyway.locationsToScan=db/migration
flyway.ignoreFutureMigrations=true
flyway.ignoreMissingMigrations=false
flyway.outOfOrder=false
#taget migration version, i.e. the version up to which the migration is done.
#migrations with a higher version number will be ignored. Default=BigInteger.valueOf(-1)
flyway.targetVersion=9223372036854775807

Related

Caused by: java.lang.IllegalStateException: A transaction manager must be provided

I am running a tasklet using Spring batch (4.1.4.RELEASE) and Spring jars (4.0.9.RELEASE) and getting the exception:
Caused by: java.lang.IllegalStateException: A transaction manager must be provided**
at org.springframework.util.Assert.state(Assert.java:385) ~[spring-core-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at org.springframework.batch.core.step.tasklet.TaskletStep.afterPropertiesSet(TaskletStep.java:129) ~[spring-batch-core-4.1.4.RELEASE.jar:4.1.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1613) ~[spring-beans-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1550) ~[spring-beans-4.0.9.RELEASE.jar:4.0.9.RELEASE]
... 41 more
Below I have shown the session factory XML-based configuration.
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:hibernate.cfg.xml" />
<property name="hibernateProperties">
<value>
hibernate.show_sql=false
hibernate.format_sql=false
hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
hibernate.query.substitutions=true 'Y', false 'N'
hibernate.cache.use_second_level_cache=true
hibernate.cache.provider_class=net.sf.ehcache.hibernate.SingletonEhCacheProvider
hibernate.cache.use_query_cache=true
</value>
</property>
</bean>
<bean id="jdbcTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
lazy-init="true">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="hibernatetransactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager"
lazy-init="true">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
I have tried some changes in Spring batch and Spring core library versions but nothing is working and I am getting the same exception.
The error happens in org.springframework.batch.core.step.tasklet.TaskletStep.afterPropertiesSet(TaskletStep.java:129) ~[spring-batch-core-4.1.4.RELEASE.jar:4.1.4.RELEASE], which means you did not set a transaction manager on your tasklet.
You did not share your tasklet's configuration, but you need to make sure a transaction manager is set on it, this is a mandatory property.

Error on configuration of JNDI lookup for WebLogic + Spring

I'm migrating an application from OC4J to WebLogic 12c and the Spring beans are giving an error I can't figure out how to solve. My question is what can be the cause of this error.
I have the following bean for the JNDI lookup:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="${datasource.jndiname}" />
<property name="lookupOnStartup">
<value>false</value>
</property>
<property name="proxyInterface">
<value>javax.sql.DataSource</value>
</property>
</bean>
The value ${datasource.jndiname} is expected to come from a config.properties file with the following line:
server.database.datasource=${datasource.jndiname}
And the value of server.database.datasource comes from a config.filter file with the line:
server.database.datasource=jdbc/DATASOURCE
This works fine with OC4J and it also works when I replace the ${datasource.jndiname} to its value jdbc/DATASOURCE in WebLogic, but it gives me the following error if I keep the reference (and I need to keep it):
JndiObjectTargetSource failed to obtain new target object; nested exception is javax.naming.NameNotFoundException: While trying to lookup '${datasource.jndiname}' didn't find subcontext '${datasource'. Resolved ''; remaining name '${datasource/jndiname}'
After some research, I found a property for the bean that fixed the error. Setting the property resourceRef to false makes the reference ${datasource.jndiname} work as expected.
In the final code shown below I also added a JndiTemplate.
<bean id="dsJndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.provider.url">t3://localhost:7001</prop>
<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="${datasource.jndiname}" />
<property name="resourceRef" value="false"/>
<property name="lookupOnStartup" value="false"/>
<property name="proxyInterface" value="javax.sql.DataSource"/>
<property name="jndiTemplate">
<ref local="dsJndiTemplate" />
</property>
</bean>

Having the property hibernate.globally_quoted_identifiers causes BoneCPDataSource not to find com.microsoft.sqlserver.jdbc.SQLServerDriver

I have an application that uses Spring with Hibernate connecting to MS SQL Server.
The application connects fine without this property:
<prop key="hibernate.globally_quoted_identifiers">true</prop>
However, I need that property as some table names/columns have reserved names and I don't want to escape them all.
The configuration is:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="mainDataSource" />
<property name="packagesToScan" value="mypackage.entity" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.show_sql">${jdbc.showSql}</prop>
<prop key="hibernate.format_sql">${jdbc.showSql}</prop>
<prop key="hibernate.use_sql_comments">${jdbc.showSql}</prop>
<prop key="hibernate.globally_quoted_identifiers">true</prop>
</props>
</property>
</bean>
<!-- BoneCP configuration -->
<bean id="mainDataSource" 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="60"/>
<property name="idleMaxAgeInMinutes" value="240"/>
<property name="maxConnectionsPerPartition" value="50"/>
<property name="minConnectionsPerPartition" value="5"/>
<property name="partitionCount" value="3"/>
<property name="acquireIncrement" value="5"/>
<property name="statementsCacheSize" value="100"/>
<property name="releaseHelperThreads" value="3"/>
</bean>
All of the properties are set. I'm using sqljdbc4.2. jdbc.driverClassName is set to com.microsoft.sqlserver.jdbc.SQLServerDriver. The JAR is in the WEB-INF/lib folder, the classpath, and the $CATALINA_HOME/lib folder. It works perfectly fine without the globally_quoted_identifiers property, but I can't figure out why adding it causes BoneCPDataSource to not be able to find the driver. Here is the error message:
Caused by: org.hibernate.MappingException: Unable to find column with logical name: my_entity_id in org.hibernate.mapping.Table(my_entity) and its related supertables and secondary tables
at org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:559)
at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:258)
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:116)
at org.hibernate.cfg.Configuration.processEndOfQueue(Configuration.java:1596)
at org.hibernate.cfg.Configuration.processFkSecondPassInOrder(Configuration.java:1519)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1420)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1844)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850)
... 33 more
[ERROR] 06/12/2016 10:44:15 [BoneCP-pool-watch-thread] [(ConnectionHandle:229)] Failed to acquire connection. Sleeping for 7000ms. Attempts left: 5
java.sql.SQLException: No suitable driver found for jdbc:sqlserver://localhost:1433;databaseName=SDC-Prod
at java.sql.DriverManager.getConnection(DriverManager.java:689)
at java.sql.DriverManager.getConnection(DriverManager.java:247)
at com.jolbox.bonecp.BoneCP.obtainRawInternalConnection(BoneCP.java:256)
at com.jolbox.bonecp.ConnectionHandle.obtainInternalConnection(ConnectionHandle.java:211)
at com.jolbox.bonecp.ConnectionHandle.<init>(ConnectionHandle.java:170)
at com.jolbox.bonecp.PoolWatchThread.fillConnections(PoolWatchThread.java:101)
at com.jolbox.bonecp.PoolWatchThread.run(PoolWatchThread.java:82)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
[ERROR] 06/12/2016 10:44:15 [BoneCP-pool-watch-thread] [(CustomThreadFactory:89)] Uncaught Exception in thread BoneCP-pool-watch-thread
java.lang.NoClassDefFoundError: com/jolbox/bonecp/hooks/ConnectionState
at com.jolbox.bonecp.ConnectionHandle.markPossiblyBroken(ConnectionHandle.java:291)
at com.jolbox.bonecp.ConnectionHandle.obtainInternalConnection(ConnectionHandle.java:241)
at com.jolbox.bonecp.ConnectionHandle.<init>(ConnectionHandle.java:170)
at com.jolbox.bonecp.PoolWatchThread.fillConnections(PoolWatchThread.java:101)
at com.jolbox.bonecp.PoolWatchThread.run(PoolWatchThread.java:82)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: com.jolbox.bonecp.hooks.ConnectionState
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1892)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1735)
... 8 more
It seemed like the find table was failing because it couldn't connect, but just can't seem to find the link between the globally_quoted_identifiers and the driver class.

Cent OS: Hibernate Envers error REVINFO table doesn't exist but revinfo exists

revinfo in small letter working correctly on local and our 2 previous different server but i have new server that doesn't working gives error REVINFO doesn't exist
previous server config :
OS : Cent OS 6.5
mysql : 5.5.40
hibernate jar: 4.1.7final
jdk 1.7
current server config :
OS : Cent OS 6.5
mysql : 5.5.40
hibernate jar: 4.1.7final
jdk 1.7
Local
Os : windows
mysql : 5.5.40
hibernate jar: 4.1.7final
jdk 1.7
both .war file are same
applicationContext.xml
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/testdb_trunk" />
<property name="username" value="root" />
<property name="password" value="root" />
<property name="minIdle" value="10" />
<property name="initialSize" value="10" />
<property name="validationQuery" value="SELECT 1 FROM DUAL"/>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="in.demo.server.datamodel" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">false</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
</props>
</property>
</bean>
thanks in advance
You have to try to provide some additional property hibernate.ejb.naming_strategy to your hibernate properties, to make your application behave similar in different environements.
You can read about it in java doc for NamingStrategy interface. It has yet some available implementations: DefaultNamingStrategy and ImprovedNamingStrategy, you can choose one of them. Or you can create your own implementation.
windows mysql default case insensitive so i have added
lower_case_table_names = 1
in
/etc/mysql/my.cnf file for cent OS.
refer for more in detail https://dba.stackexchange.com/questions/59407/how-to-make-mysql-table-name-case-insensitive-in-ubuntu

Failed to determine Hibernate PersistenceProvider

I am trying to configure LocalContainerEntityManagerFactoryBean without persisten.xml file.
this is my dataSource - it works for Hibernate SessionFactory - so, it is ok.
<bean id="dataSource"
class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
this is my LocalContainerEntityManagerFactoryBean
<bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="application.models" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">create-drop</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
</props>
</property>
</bean>
An exception that i am getting:
...Could not instantiate bean class [org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter]: Constructor threw exception; nested exception is java.lang.IllegalStateException: Failed to determine Hibernate PersistenceProvider
I read documentation, and i know that LocalContainerEntityManagerFactoryBean has such property, and similar style of creating LocalContainerEntityManagerFactoryBean works in Spring in Action 3 and here: http://softwarecave.org/2014/03/15/using-jpa-and-jta-with-spring/
Maybe You have an idea what i am doing wrong or at least what spring want tell me via this exception ?
Thanks in advance,
Cheers :)
P.S to be clear, Failed to determine Hibernate PersistenceProvider doesn't mean that spring expect persistence.xml - this should be error like: No persistence units parsed from {classpath*:META-INF/persistence.xml}
RESOLVED:
thanks JB Nizet - if You will have similar problem add:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.6.Final</version>
</dependency>
to pom.xml
Below code works for me.
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" p:dataSource-ref="dataSource">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
</bean>
</property>
</bean>
With hibernate = 4.3.5.Final
spring=4.1.4.RELEASE

Categories