I'm working on a dependency migration task trying to migrate the Spring codebase from Spring 2.6.9 to Spring 2.7.0. However, am facing some issues related to the migration H2.
I read the migration guide of the Spring 2.7 which states
Spring Boot 2.7 has upgraded to H2 2.1.120. H2 2.x is backwards incompatible and fixes a number of security vulnerabilities. See the H2 changelog and migration guide for details of the changes and how to handle the upgrade.
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto = create
@Configuration
public class DataSourceConfig {
@Bean(name = "sessionFactory")
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(datasource());
sessionFactory.setHibernateProperties(properties());
return sessionFactory;
}
@Bean(name = "dataSource")
JdbcConnectionPool datasource() {
return JdbcConnectionPool.create("jdbc:h2:mem:testdb", "user", "password");
}
@Bean
public PlatformTransactionManager hibernateTransactionManager() {
HibernateTransactionManager transactionManager
= new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
@Bean
Properties properties() {
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
return properties;
}
}
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
</parent>
..
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>9.1.0</version>
</dependency>
When running my application I find below useful stack trace logs:
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'dataSource' defined in class path resource
[DataSourceConfig.class]: Initialization of bean failed; nested exception is
org.springframework.aop.framework.AopConfigException:
Could not generate CGLIB subclass of class org.h2.jdbcx.JdbcConnectionPool:
Common causes of this problem include using a final class or a non-visible class;
nested exception is java.lang.IllegalArgumentException: Cannot subclass final class org.h2.jdbcx.JdbcConnectionPoo
Caused by: org.springframework.aop.framework.AopConfigException:
Could not generate CGLIB subclass of class org.h2.jdbcx.JdbcConnectionPool:
Common causes of this problem include using a final class or a non-visible class;
nested exception is java.lang.IllegalArgumentException: Cannot subclass final class org.h2.jdbcx.JdbcConnectionPool
...
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class org.h2.jdbcx.JdbcConnectionPool
at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:660) ~[spring-core-5.3.20.jar:5.3.20]
I've read below questions/answers:
Could not generate CGLIB subclass of class - Common causes ... final class
Spring AspectJ fails when double-proxying interface: Could not generate CGLIB subclass of class
After spring upgrade: could not generate CGLIB subclass of class class com.sun.proxy.$Proxy
However, didn't find anything useful.
I'd appreciate any help. Thanks!
As commented by @M. Deinum
Spring will create a
DataSource
for you based on the properties
We don't need to create a datasource
explicitly, and as far as sessionFactory
is concerned. We can create one using LocalSessionFactoryBean
as below:
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import javax.sql.DataSource
@Configuration
public class DataSourceConfig {
@Bean(name = "sessionFactory")
LocalSessionFactoryBean sessionFactory(DataSource dataSource) {
final var sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
return sessionFactory;
}
}