I have a Spring Boot Camel project which uses Hibernate and its L2 cache system enabled. The L2 Cache provider I used is Redis and the application connects through Spring Redission starter.
I package the application through maven (basically a FAT jar) and it's required that I have to run the application independently. I have placed all property files related to the application (incl. application.properties file) inside a config folder.
The reason that I want all of the property files out of the fat jar is that I want the values of the properties to be configurable and not that I have to build a jar file often for minor configuration changes.
I build the jar using maven's maven-jar-plugin through Eclipse by maven install option in the maven project's Run Configuration.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3</version>
<configuration>
<excludes>
<exclude>**/*.properties</exclude>
<exclude>**/*.json</exclude>
<exclude>**/*.xml</exclude>
</excludes>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.elstacker.main</mainClass>
</manifest>
<!-- <manifestEntries>
<Class-Path>conf/</Class-Path>
</manifestEntries> -->
</archive>
</configuration>
</plugin>
I have also tried commenting the above plugin and just used the resources tag/coordinates for excluding the files that are not required inside the .jar file.
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>*.properties</exclude>
<exclude>*.json</exclude>
<exclude>*.xml</exclude>
</excludes>
<filtering>true</filtering>
</resource>
</resources>
The standalone application server layout looks like the below:
Project Layout 1
Project Layout 2
As the application also involves accessing a Redis Server for hibernate L2 Cache, there are few hibernate related property entries mentioned the application.properties file. The snippet of L2 Cache configuration is mentioned below:
spring.jpa.properties.hibernate.cache.auto_evict_collection_cache=false
spring.jpa.properties.hibernate.generate_statistics=false
spring.jpa.properties.hibernate.cache.use_second_level_cache=true
spring.jpa.properties.hibernate.cache.use_query_cache=true
spring.jpa.properties.hibernate.javax.cache.missing_cache_strategy=create
spring.jpa.properties.cache.region.factory_class=com.redis.RedissionConfig
spring.jpa.properties.javax.persistence.sharedCache.mode=ENABLE_SELECTIVE
I would've used a custom RedissionConfigFactory for starting the redis connection manager during application startup. The code looks like below:
public class RedissionConfig extends org.redisson.hibernate.RedissonRegionFactory{
private static final long serialVersionUID = 1L;
Logger log = LogManager.getLogger("com.fss.convertor");
@Bean
public RedissonConnectionFactory redissonConnectionFactory(RedissonClient redisson) {
return new RedissonConnectionFactory(redisson);
}
@Bean(destroyMethod = "shutdown")
public RedissonClient redisson() throws IOException {
return Redisson.create(buildConfigFile());
}
public Config buildConfigFile() {
//Resource resource = null;
//InputStream input = null;
Config config = null;
File file=null;
try {
//resource = new ClassPathResource("redisson.json");
//input = resource.getInputStream();
//File file = resource.getFile();
ClassPathResource path = new ClassPathResource("redisson.json");
log.info("path ::: "+path.getPath());
file = new File(path.getPath());
log.info("file :::"+ file.exists() +":::" + file.getAbsolutePath());
config = Config.fromJSON(file);
}catch(Exception e) {
log.info("Exception ::: "+e.getMessage());
}finally {}
return config;
}
@Bean
CacheManager cacheManager(RedissonClient redissonClient) {
Map<String, CacheConfig> config = new HashMap<>();
CacheConfig configItem = new CacheConfig(TimeUnit.MINUTES.toMillis(60), TimeUnit.MINUTES.toMillis(30));
config.put("domainCache",configItem);
return new RedissonSpringCacheManager(redissonClient, config);
}
}
The application starts up and works fine when I am using Eclipse. But when I try to start up the application as a standalone application after packaging the application through maven, the application is unable to load the custom RedisConfigFactory class file as this file is now located in the .jar file and it feels to me that hibernate is unable to find the class file mentioned in the property spring.jpa.properties.cache.region.factory_class=com.redis.RedissionConfig
I am left with an exception as mentioned below:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2019-09-24 17:10:52.559 [ERROR] [SpringApplication.java:821] - Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.cache.spi.CacheImplementor]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1778) ~[spring-beans-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593) ~[spring-beans-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515) ~[spring-beans-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1105) ~[spring-context-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) ~[spring-context-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549) ~[spring-context-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.1.6.RELEASE.jar!/:2.1.6.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:742) [spring-boot-2.1.6.RELEASE.jar!/:2.1.6.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:389) [spring-boot-2.1.6.RELEASE.jar!/:2.1.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:311) [spring-boot-2.1.6.RELEASE.jar!/:2.1.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1213) [spring-boot-2.1.6.RELEASE.jar!/:2.1.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1202) [spring-boot-2.1.6.RELEASE.jar!/:2.1.6.RELEASE]
at com.messageconvertorstarter.MessageConvertorStarter.main(MessageConvertorStarter.java:41) [classes!/:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_171]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_171]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_171]
at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_171]
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:47) [MessageConvertor-0.0.2.jar:?]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:86) [MessageConvertor-0.0.2.jar:?]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:50) [MessageConvertor-0.0.2.jar:?]
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51) [MessageConvertor-0.0.2.jar:?]
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.cache.spi.CacheImplementor]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:402) ~[spring-orm-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:377) ~[spring-orm-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1837) ~[spring-beans-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1774) ~[spring-beans-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
... 24 more
Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.cache.spi.CacheImplementor]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:275) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.service.internal.SessionFactoryServiceRegistryImpl.getService(SessionFactoryServiceRegistryImpl.java:109) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:239) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:467) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:939) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57) ~[spring-orm-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:390) ~[spring-orm-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:377) ~[spring-orm-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1837) ~[spring-beans-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1774) ~[spring-beans-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
... 24 more
Caused by: java.lang.IllegalStateException: Cache provider not started
at org.hibernate.cache.spi.AbstractRegionFactory.verifyStarted(AbstractRegionFactory.java:65) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.cache.spi.support.RegionFactoryTemplate.buildTimestampsRegion(RegionFactoryTemplate.java:66) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.cache.internal.EnabledCaching.<init>(EnabledCaching.java:80) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.engine.spi.CacheInitiator.initiateService(CacheInitiator.java:33) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.engine.spi.CacheInitiator.initiateService(CacheInitiator.java:24) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.service.spi.SessionFactoryServiceInitiator.initiateService(SessionFactoryServiceInitiator.java:30) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.service.internal.SessionFactoryServiceRegistryImpl.initiateService(SessionFactoryServiceRegistryImpl.java:68) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.service.internal.SessionFactoryServiceRegistryImpl.getService(SessionFactoryServiceRegistryImpl.java:109) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:239) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:467) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:939) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57) ~[spring-orm-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:390) ~[spring-orm-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:377) ~[spring-orm-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1837) ~[spring-beans-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1774) ~[spring-beans-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
... 24 more
Caused by: org.hibernate.cache.CacheException: Unable to locate Redisson configuration
at org.redisson.hibernate.RedissonRegionFactory.createRedissonClient(RedissonRegionFactory.java:97) ~[redisson-hibernate-53-3.10.0.jar!/:?]
at org.redisson.hibernate.RedissonRegionFactory.prepareForUse(RedissonRegionFactory.java:78) ~[redisson-hibernate-53-3.10.0.jar!/:?]
at org.hibernate.cache.spi.AbstractRegionFactory.start(AbstractRegionFactory.java:91) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.cache.internal.EnabledCaching.<init>(EnabledCaching.java:77) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.engine.spi.CacheInitiator.initiateService(CacheInitiator.java:33) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.engine.spi.CacheInitiator.initiateService(CacheInitiator.java:24) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.service.spi.SessionFactoryServiceInitiator.initiateService(SessionFactoryServiceInitiator.java:30) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.service.internal.SessionFactoryServiceRegistryImpl.initiateService(SessionFactoryServiceRegistryImpl.java:68) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.service.internal.SessionFactoryServiceRegistryImpl.getService(SessionFactoryServiceRegistryImpl.java:109) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:239) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:467) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:939) ~[hibernate-core-5.3.10.Final.jar!/:5.3.10.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57) ~[spring-orm-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:390) ~[spring-orm-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:377) ~[spring-orm-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1837) ~[spring-beans-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1774) ~[spring-beans-5.1.8.RELEASE.jar!/:5.1.8.RELEASE]
... 24 more
I have also tried other means of injecting the class file by replacing spring.jpa.properties.cache.region.factory_class=com.redis.RedissionConfig
with the one like below:
- (if in-case the class may have been injected by spring to hibernate class loaders)
- spring.jpa.properties.cache.region.factory_class=#redissionConfig as well as
- spring.jpa.properties.cache.region.factory_class=${redissionConfig}
However, it's still of no use. I am faced with the same exception as above.
Could anyone please help me out on how to load/reference class files located inside a .jar file from spring boot's application.properties file which is located out of its actual package structure.
Any help would be really appreciated as I am terribly stuck up here not knowing how to solve this issue.