I am having issues with setting up multi-tenancy support for my web application with a separate database approach using Spring + JPA + Hibernate.
I have tried the Hibernate way using my own implementations of CurrentTenantIdentifierResolver and AbstractMultiTenantConnectionProvider, and the Spring one using AbstractRoutingDataSource. I'll use the AbstractRoutingDataSource solution, that I named UserRoutingDataSource, to explain my problem.
What I am trying to achieve is the following :
I have a "master" database with all the data concerning the users and their databases
When a user logs in I save his database id in a session scoped bean named UserSession
My UserRoutingDataSource's targetDataSources needs to be filled with datasources representing all the databases of my master database's CustomDatabases table.
When a connection is needed, my UserRoutingDataSource's determineCurrentLookupKey needs to retrieve the database id from the user's UserSession instance.
In both cases (Hibernate way / Spring way) I end up with a circular reference exception. The issue arises when I try to autowire my CustomDatabasesDAO and my UserSession in UserRoutingDataSource.
This is the exception I get :
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userEntityManagerFactory' defined in class path resource [MyApp/webapp/WEB-INF/config/applicationContext.xml]: Cannot resolve reference to bean 'userRoutingDataSource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userRoutingDataSource' defined in class path resource [MyApp/webapp/WEB-INF/config/applicationContext.xml]: Unsatisfied dependency expressed through constructor argument with index 0 of type [myApp.java.data.dao.Global.CustomDatabasesDAO]: : Error creating bean with name 'customDatabasesDAO': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'userEntityManagerFactory': FactoryBean which is currently in creation returned null from getObject; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customDatabasesDAO': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'userEntityManagerFactory': FactoryBean which is currently in creation returned null from getObject
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1481)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1226)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1051)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:828)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:446)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:328)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4728)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5162)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1399)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userRoutingDataSource' defined in class path resource [MyApp/webapp/WEB-INF/config/applicationContext.xml]: Unsatisfied dependency expressed through constructor argument with index 0 of type [myApp.java.data.dao.Global.CustomDatabasesDAO]: : Error creating bean with name 'customDatabasesDAO': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'userEntityManagerFactory': FactoryBean which is currently in creation returned null from getObject; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customDatabasesDAO': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'userEntityManagerFactory': FactoryBean which is currently in creation returned null from getObject
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
... 24 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customDatabasesDAO': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'userEntityManagerFactory': FactoryBean which is currently in creation returned null from getObject
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:357)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1192)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1116)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
... 34 more
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'userEntityManagerFactory': FactoryBean which is currently in creation returned null from getObject
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:181)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:127)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1584)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:253)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
at org.springframework.orm.jpa.EntityManagerFactoryUtils.findEntityManagerFactory(EntityManagerFactoryUtils.java:130)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findNamedEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:556)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:538)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:707)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.getResourceToInject(PersistenceAnnotationBeanPostProcessor.java:680)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:169)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:354)
... 46 more
What I don't understand is why I get this exception when my CustomDatabasesDAO doesn't have a single reference to userEntityManagerFactory. The only relevant thing that I can think of in CustomDatabasesDAO is my call to the master database's entityManager :
#PersistenceContext(unitName = "masterEntityManagerFactory")
private EntityManager masterEntityManager;
For more context, here are my UserRoutingDataSource file and the relevant parts from my application context file.
UserRoutingDataSource
public class UserRoutingDataSource extends AbstractRoutingDataSource {
/*private CustomDatabasesDAO customDatabasesDAO;
#Autowired
public void setCustomDatabasesDAO(final CustomDatabasesDAO customDatabasesDAO)
{
this.customDatabasesDAO = customDatabasesDAO;
}*/
#Autowired
private UserSession session;
/*#Autowired
public void setUserSession(final UserSession session)
{
this.session = session;
}*/
#Autowired
public UserRoutingDataSource(CustomDatabasesDAO customDatabasesDAO) {
Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
for(CustomDatabases database : customDatabasesDAO.findDatabasesByDeleted(0))
{
// All the information necessary for the datasource will eventually be retrieved from the database variable
DriverManagerDataSource datasource = new DriverManagerDataSource();
datasource.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
datasource.setUrl("jdbc:sqlserver://localhost:1433;databaseName=" + database.getCdboAliasName() + ";");
datasource.setUsername("username");
datasource.setPassword("password");
targetDataSources.put(String.valueOf(database.getCdboDatabaseId()), datasource);
}
setTargetDataSources(targetDataSources);
}
#Override
protected Object determineCurrentLookupKey() {
return session.getCdboDatabaseId();
}
}
Application context
/*<!--<bean id="currentTenantIdentifierResolverImpl" class="myApp.java.config.CurrentTenantIdentifierResolverImpl" />
<bean id="multiTenantConnectionProvider" class="myApp.java.config.MultiTenantConnectionProvider" />-->*/
<bean id="masterDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
<property name="url" value="jdbc:sqlserver://localhost:1433;databaseName=myDatabase;" />
<property name="username" value="sa" />
<property name="password" value="password" />
</bean>
<bean id="masterEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="masterDataSource" />
<property name="packagesToScan" value="myApp.java.data.model" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.use_outer_join">true</prop>
</props>
</property>
</bean>
<bean id="userRoutingDataSource" class="myApp.java.config.UserRoutingDataSource">
<property name="targetDataSources">
<map />
</property>
</bean>
<bean id="userEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="userRoutingDataSource" />
<property name="packagesToScan" value="myApp.java.data.model" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<map>
<entry key="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect" />
<entry key="hibernate.show_sql" value="false" />
<entry key="hibernate.use_outer_join" value="true" />
/*<!--<entry key="hibernate.tenant_identifier_resolver" value-ref="currentTenantIdentifierResolverImpl" />
<entry key="hibernate.multi_tenant_connection_provider" value-ref="multiTenantConnectionProvider" />
<entry key="hibernate.multiTenancy" value="DATABASE" />-->*/
</map>
</property>
</bean>
<!-- Transaction managers -->
<tx:annotation-driven />
<bean id="masterTransactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="masterEntityManagerFactory" />
<qualifier value="master" />
</bean>
<bean id="userTransactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="userEntityManagerFactory" />
<qualifier value="user" />
</bean>
I have tried so many things that I am not sure if I still understand how dependency injection works. And I have no idea what I might be missing.
Thanks for you help.
SOLUTION :
I solved my issue thanks to Roman's answer. I also gave up on the idea of using my session scoped bean to determine my current lookup key and I use my Spring Security authentication instead. When a user logs in I do the following :
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
UsernamePasswordAuthenticationToken newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(), authorities);
HashMap<String, Object> details = new HashMap<String, Object>();
details.put("databaseId", session.getCdboDatabaseId());
newAuth.setDetails(details);
SecurityContextHolder.getContext().setAuthentication(newAuth);
The important part being the setDetails(details) on my user's UsernamePasswordAuthenticationToken.
Here is the current state of my (working) configuration :
UserRoutingDataSource
#Component
public class UserRoutingDataSource extends AbstractRoutingDataSource {
#Autowired
public UserRoutingDataSource(CustomDatabasesDAO customDatabasesDAO) {
Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
for(CustomDatabases database : customDatabasesDAO.findDatabasesByDeleted(0))
{
DriverManagerDataSource datasource = new DriverManagerDataSource();
datasource.setDriverClassName(database.getCdboDriverName());
datasource.setUrl("jdbc:sqlserver://"+database.getCdboServer()+":"+database.getCdboPort()+";databaseName="+database.getCdboAliasName() + ";");
datasource.setUsername(database.getCdboUserName());
datasource.setPassword(database.getCdboPassword());
targetDataSources.put(database.getCdboDatabaseId(), datasource);
}
/*
* This default datasource is necessary because for some reason (Hibernate, JPA related ?) the routing datasource
* calls the "determineCurrentLookupKey()" on startup which returned null ("default" now) because there is no Authentication at startup yet.
*/
targetDataSources.put("default", new DriverManagerDataSource());
setTargetDataSources(targetDataSources);
afterPropertiesSet();
}
#Override
protected Object determineCurrentLookupKey() {
UsernamePasswordAuthenticationToken auth = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
if (auth != null && auth.getDetails() instanceof Map)
{
HashMap<String, Object> details = (HashMap<String, Object>) auth.getDetails();
return details.get("databaseId");
}
return "default";
}
}
Application context
<bean id="masterDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
<property name="url" value="jdbc:sqlserver://localhost:1433;databaseName=myDatabase;" />
<property name="username" value="myUser" />
<property name="password" value="myPassword" />
</bean>
<bean id="masterEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="masterEntityManagerFactory" />
<property name="dataSource" ref="masterDataSource" />
<property name="packagesToScan" value="myApp.java.data.model" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.use_outer_join">true</prop>
</props>
</property>
</bean>
<bean id="userEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="userEntityManagerFactory" />
<property name="dataSource" ref="userRoutingDataSource" />
<property name="packagesToScan" value="myApp.java.data.model" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<map>
<entry key="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect" />
<entry key="hibernate.show_sql" value="false" />
<entry key="hibernate.use_outer_join" value="true" />
</map>
</property>
</bean>
<!-- Transaction managers -->
<tx:annotation-driven />
<bean id="masterTransactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="masterEntityManagerFactory" />
<qualifier value="master" />
</bean>
<bean id="userTransactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="userEntityManagerFactory" />
<qualifier value="user" />
</bean>
Spring iterates over all EntityManagerFactorys inside of EntityManagerFactoryUtils.findEntityManagerFactory() to find out the factory with the property persistenceUnitName value equals to #PersistenceUnit's attribute unitName value. Only if no candidate has been found the bean with the name of unitName value will be used. Therefore userEntityManagerFactory gets instantiated during this process.
As a workaround you could try to make use of regular #Autowired instead of #PersistenceUnit in CustomDatabasesDAO class.
Related
I am trying to use Hikari connection pooling for my spring based app using xml based bean configuration. Below is my Hikari config bean and I am using the Db2 as my database.
<bean id="HikariConfig_UId_Primary" class="com.zaxxer.hikari.HikariConfig">
<property name="poolName" value="uidPrimaryCP" />
<property name="connectionTestQuery" value="select 1 from sysibm.systables fetch first row only with UR" />
<property name="dataSourceClassName" value="${Jdbc_DataSourceClassName}" />
<property name="maximumPoolSize" value="${Jdbc_MaxPoolSize}"/>
<property name="idleTimeout" value="${Jdbc_IdleTimeOut}" />
<property name="maxLifetime" value="${Jdbc_MaxLifeTime}" />
<property name="connectionTimeout" value="${Jdbc_ConnTimeOut}" />
<property name="dataSourceProperties">
<props>
<prop key="url">${Jdbc_UID_Primary}</prop>
<prop key="user">${Jdbc_UserId}</prop>
<prop key="password">${Jdbc_Password}</prop>
</props>
</property>
</bean>
<bean id="UID_Primary_DataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
<constructor-arg ref="HikariConfig_UId_Primary" />
</bean>
It failing to register the bean, saying the database url property - url does not exists on target class com.ibm.db2.jcc.DB2SimpleDataSource.
below is the complete stack trace..
com.ibm.ws.webcontainer.webapp.WebApp notifyServletContextCreated SRVE0283E: Exception caught while initializing context: {0}
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'UID_Primary_DataSource' defined in class path resource [config/SpringDbContext.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.zaxxer.hikari.HikariDataSource]: Constructor threw exception; nested exception is java.lang.RuntimeException: Property url does not exist on target class com.ibm.db2.jcc.DB2SimpleDataSource
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:278)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1114)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1017)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at com.deere.u90.iafservice.unifieduser.application.ApplicationRegistry.loadSpringLdapContext(ApplicationRegistry.java:
any help is greatly appreciated..
thanks..
I've connected to Hikari using spring boot but not with xml configuration. See my post here
I think, adding up below property should fix error.
<property name="jdbcUrl" value="" />
<property name="username" value="" />
<property name="password" value="" />
You seem to have several things wrong. You didn't post the value of variable ${Jdbc_DataSourceClassName} be it appears to resolve to DB2SimpleDataSource at runtime. Per this IBM KnowledgeCenter topic, that datasource is not poolable and since you started the post with "I am trying to use Hikari connection pooling", I'm assuming you want a poolable DS like com.ibm.db2.jcc.DB2ConnectionPoolDataSource as described here.
The second problem is that the DB2 Datasource classes don't support a url property, only the DB2 DriverManager interface supports it. The KC topic for the abstract base of the DB2 data source classes, DB2BaseDataSource, says
You can set all properties on a DataSource or in the url parameter in
a DriverManager.getConnection call.
url is not one of the listed properties, so you're going to need to establish the connection to the dataasource using the hostname, port, etc properties
Exception is: Ignite Discovery SPI implementation does not support node ordering and cannot be used with cache (use SPI with DiscoverySpiOrderSupport annotation, like TcpDiscoverySpi)
<bean id="igniteConfig" class="org.apache.ignite.configuration.IgniteConfiguration">
<property name="cacheConfiguration">
<util:list>
<bean class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="rateLimitterBuckets" />
<property name="cacheMode" value="REPLICATED" />
<property name="rebalanceMode" value="SYNC" />
<property name="expiryPolicyFactory">
<bean class="javax.cache.configuration.FactoryBuilder.SingletonFactory">
<constructor-arg>
<bean class="javax.cache.expiry.TouchedExpiryPolicy">
<constructor-arg>
<bean class="javax.cache.expiry.Duration">
<constructor-arg value="DAYS" />
<constructor-arg value="1" />
</bean>
</constructor-arg>
</bean>
</constructor-arg>
</bean>
</property>
<property name="eagerTtl" value="true" />
</bean>
</util:list>
</property>
<property name="gridLogger">
<bean class="org.apache.ignite.logger.log4j.Log4JLogger" />
</property>
<property name="includeEventTypes">
<list>
<util:constant static-field="org.apache.ignite.events.EventType.EVT_CLIENT_NODE_DISCONNECTED" />
<util:constant static-field="org.apache.ignite.events.EventType.EVT_CLIENT_NODE_RECONNECTED" />
</list>
</property>
<property name="metricsLogFrequency" value="3600000" />
<property name="discoverySpi">
<bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
<property name="ipFinder">
<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder">
<property name="addresses">
<list>
<value>127.0.0.1:47500..47509</value>
</list>
</property>
</bean>
</property>
</bean>
</property>
</bean>
I do use TcpDiscoverySpi. I checked sources it's marked with #DiscoverySpiOrderSupport(true) annotation.
But still exception is there. Hence the question: how to fix that?
UPD 1: Adding a stack trace (I stripped part that is irrelevant -- I have couple beans dependent on Ignite, so they cant be created because of this exception)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ignite' defined in class path resource [farm-connection-ignite.xml]: Invocation of init method failed; nested exception is class org.apache.ignite.IgniteCheckedException: Discovery SPI implementation does not support node ordering and cannot be used with cache (use SPI with #DiscoverySpiOrderSupport annotation, like TcpDiscoverySpi)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:372)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1123)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
... 76 more
Caused by: class org.apache.ignite.IgniteCheckedException: Discovery SPI implementation does not support node ordering and cannot be used with cache (use SPI with #DiscoverySpiOrderSupport annotation, like TcpDiscoverySpi)
at org.apache.ignite.internal.IgnitionEx$IgniteNamedInstance.initializeDefaultCacheConfiguration(IgnitionEx.java:2234)
at org.apache.ignite.internal.IgnitionEx$IgniteNamedInstance.initializeConfiguration(IgnitionEx.java:2179)
at org.apache.ignite.internal.IgnitionEx$IgniteNamedInstance.start0(IgnitionEx.java:1678)
at org.apache.ignite.internal.IgnitionEx$IgniteNamedInstance.start(IgnitionEx.java:1652)
at org.apache.ignite.internal.IgnitionEx.start0(IgnitionEx.java:1080)
at org.apache.ignite.internal.IgnitionEx.start(IgnitionEx.java:578)
at org.apache.ignite.IgniteSpring.start(IgniteSpring.java:66)
at org.apache.ignite.IgniteSpringBean.afterPropertiesSet(IgniteSpringBean.java:160)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
... 92 more
Well it appears It's not a jar hell, I've checked the classpath.
It's a Spring Context AOP hell, when Spring wraps beans with Proxies. Proxy has zero annotations. Hence IgniteUtils.discoOrdered don't see those.
In my application context xml config I have
<bean id="facadeMonitoringAdvisor" class="net.bull.javamelody.MonitoringSpringAdvisor">
<property name="pointcut">
<bean class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="pattern" value=".*Impl.*" />
<property name="excludedPattern" value=".*PerfSens.*" />
</bean>
</property>
</bean>
Now interesting questions are:
why it worked in 1.7.0. There must have been some code that was able to work with proxies.
why it's even affecting TcpDiscoverySpi bean, pattern clearly shouldn't match TcpDiscoverySpi
I'll update this answer if I find out more.
I know this is a commonly asked question, but none of the solutions available are working out for me.
Below is my booltstraps.xml:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!--
This configuration file configures the Database Access Object or DAO objects.
It is used at system start to bootstrap configurations.
DAO objects will also be used by the main PassMark application.
-->
<bean class="com.passmarksecurity.utils.AppContext" id="appContext">
<description>Simple bean to handle initializations</description>
</bean>
<bean class="com.company.csd.dao.transaction.CompanyHibernateTransactionManager" id="transactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource" id="dataSource">
<description>
Database configuration settings.
<!-- config-->
<property name="driverClassName">
<value>com.microsoft.sqlserver.jdbc.SQLServerDriver</value>
</property>
<property name="url">
<value>jdbc:sqlserver://localhost:1433;databaseName=CORE</value>
</property>
<property name="username">
<value>core_user</value>
</property>
<property name="password">
<value>core_user</value>
</property>
<!-- config-->
</bean>
<!-- Configure DAOFactory -->
<bean class="com.passmarksecurity.dao.api.DAOFactory" id="daoFactory" init-method="configPostProcess">
<property name="DAOConfig">
<ref bean="daoConfig"/>
</property>
</bean>
<!-- IMPORTANT: Configure this setting first -->
<!-- This is for Oracle configuration with database images -->
<bean class="com.passmarksecurity.dao.config.DAOConfigMSSQL" id="daoConfig"/>
<bean class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" id="sessionFactory" lazy-init="true">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.cache.use_second_level_cache">false</prop>
<prop key="hibernate.cache.use_query_cache">false</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
</bean>
</beans>
When the application runs I get the below exception:
- <Tool failed: Error creating bean with name 'transactionManager' defined in class path resource [pmBootstrapConfigs.xml]: Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [pmBootstrapConfigs.xml]: Invocation of init method failed; nested exception is org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set>
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in class path resource [pmBootstrapConfigs.xml]: Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [pmBootstrapConfigs.xml]: Invocation of init method failed; nested exception is org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1475)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1220)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:762)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [pmBootstrapConfigs.xml]: Invocation of init method failed; nested exception is org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1572)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
... 17 more
Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set
at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:104)
at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:71)
at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:205)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:111)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:234)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:206)
at org.hibernate.cfg.Configuration.buildTypeRegistrations(Configuration.java:1887)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1845)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1930)
at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:372)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:454)
at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:439)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1631)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1568)
... 24 more
if I add <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>explicitly to the hibernate properties it starts working.
The most common answer available online is that there is some issue in connecting to the DB. So I tried writing a separate piece of code to just access the DB with the same details, and it worked.
Dont know what the problem is.
In your XML Spring configuration, you must update :
<bean class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" id="sessionFactory" lazy-init="true">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.cache.use_second_level_cache">false</prop>
<prop key="hibernate.cache.use_query_cache">false</prop>
<prop key="hibernate.show_sql">false</prop>
<!-- HERE THE DIALECT CONFIGURATION -->
</props>
</property>
</bean>
From Hibernate documentation, you must provide the dialect as following :
A dialect for Microsoft SQL Server 2008 with JDBC Driver 3.0 and above
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServer2008Dialect</prop>
A dialect for Microsoft SQL Server 2000 and 2005
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
if you specify your database name you won't need to set the dialect. To do so you can use JpaVendorAdaptor as a property for org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean
or HibernatePersistenceProvider (for hibernate versions lower than 5)
In this case if it is microsoft sql server
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="true" />
<property name="database" value="SQL_SERVER" />
</bean>
</property>
I had similar issue while testing Mysql-8 with Hibernate-5 & Spring-5. Initially, I had <prop key="dialect">org.hibernate.dialect.MySQL8Dialect</prop> in hibernateProperties tag. After 10 mins of testing I was able to add a fix by replacing <prop key="dialect"> with <prop key="dialect">.
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="packagesToScan" value="com.model"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL8Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
I am following this link:
http://www.mkyong.com/spring/spring-quartz-scheduler-example/
Everything is working fine. The tutorial shows 3 classes and pom file.
I want to make it work with 2 classes.
However I am having issues.
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Loader
{
public static void main( String[] args ) throws Exception
{
new ClassPathXmlApplicationContext("Spring-Quartz.xml");
}
}
This is the second class
public class Runner extends QuartzJobBean
{
Runner rRun = new Runner();
public void printMe() {
System.out.println(" Quartz Running! ~");
}
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException
{
rRun.printMe();
}
}
This is the pom bean config file:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean name="loader"
class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="Loader" />
<property name="jobDataAsMap">
<map>
<entry key="rRun" value-ref="rRun" />
</map>
</property>
</bean>
<!--
<bean id="loader"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="rRun" />
<property name="targetMethod" value="printMe" />
</bean>
-->
<bean id="myPropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="application.properties"/>
<property name="placeholderPrefix" value="${props:"/>
</bean>
<!-- Simple Trigger -->
<bean id="simpleTrigger"
class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail" ref="loader" />
<property name="repeatInterval" value="${props:repeatInterval}" />
<property name="startDelay" value="${props:startDelay}" />
</bean>
<!-- Cron Trigger -->
<bean id="cronTrigger"
class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="runner" />
<property name="cronExpression" value="${props:cronExpression}" />
</bean>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobDetails">
<list>
<ref bean="runner" />
</list>
</property>
<property name="triggers">
<list>
<ref bean="simpleTrigger" />
</list>
</property>
</bean>
</beans>
Where did I go wrong?
EDIT:
My issues are:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'runner' defined in class path resource [Spring-Quartz.xml]: Cannot resolve reference to bean 'rRun' while setting bean property 'jobDataAsMap' with key [TypedStringValue: value [rRun], target type [null]]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'rRun' is defined
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedMap(BeanDefinitionValueResolver.java:378)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:161)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1325)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1086)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at Loader.main(Loader.java:9)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'rRun' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:527)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1083)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:274)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:322)
... 17 more
The exception is in regard to your loader bean. It cannot be found in your bean factory or application context:
<bean name="loader"
class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="Loader" />
<property name="jobDataAsMap">
<map>
<entry key="rRun" value-ref="rRun" />
</map>
</property>
</bean>
The jobDataAsMap property has an entry that is attempting to reference another bean named rRun, which doesn't exist in your bean configuration. You probably mean to be adding your class Runner into your bean configuration, like so:
<bean id="rRun" class="package.of.your.class.Runner" />
This will allow the loader bean to find your class in its application context.
in my web application developped with GWT, Hibernate ans Spring, I encounter when setting the jobClass bean in the application-context.xml file.
I get this error at runtime :
Error 500 Error creating bean with name 'schedulerFactory' defined in class path resource [application-context.xml]:
Cannot resolve reference to bean 'cronTrigger' while setting bean property 'triggers' with key [0];
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'cronTrigger' defined in class path resource [application-context.xml]:
Cannot resolve reference to bean 'exampleJob1' while setting bean property 'jobDetail';
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'exampleJob1' defined in class path resource [application-context.xml]:
Initialization of bean failed;
nested exception is org.springframework.beans.TypeMismatchException:
Failed to convert property value of type [fr.web.utils.ExampleJob] to required type [java.lang.Class] for property 'jobClass';
nested exception is java.lang.IllegalArgumentException:
Cannot convert value of type [fr.web.utils.ExampleJob] to required type [java.lang.Class] for property 'jobClass':
PropertyEditor [org.springframework.beans.propertyeditors.ClassEditor] returned inappropriate value
Here is my Java class :
public class ExampleJob extends QuartzJobBean {
private AbsenceDao absenceDao;
#Override
protected void executeInternal(JobExecutionContext context)
throws JobExecutionException {
List untreatedDemands = new ArrayList();
untreatedDemands = absenceDao.getDemandsAskedNotValidated();
}
public AbsenceDao getAbsenceDao() {
return absenceDao;
}
public void setAbsenceDao(AbsenceDao absenceDao) {
this.absenceDao = absenceDao;
}
}
and here is my application-context.xml :
<!-- variables d'environnement - fichier properties -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" id="placeholderconfig">
<property name="fileEncoding" value="UTF-8"/>
<property name="locations">
<list>
<value>classpath:internal.properties</value>
</list>
</property>
</bean>
<!-- Configuration du crontrigger -->
<bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTrigger" />
</list>
</property>
</bean>
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
<ref local="exampleJob1" />
</property>
<property name="cronExpression">
<util:constant static-field="fr.web.utils.APP_VAR.CRON_EXPRESSION" />
</property>
</bean>
<bean id="jobClass" class="fr.web.utils.ExampleJob">
<property name="absenceDao" ref="absenceDao"/>
</bean>
<bean id="exampleJob1" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" ref="jobClass" />
<property name="jobDataAsMap">
<map>
<entry key="timeout" value="5" />
</map>
</property>
</bean>
<tx:annotation-driven transaction-manager="hibernateTransactionManager"/>
<!-- Bean containing all the properties of the application -->
<bean class="fr.web.utils.ApplicationProperties" id="applicationProperties" lazy-init="true" scope="singleton">
<constructor-arg index="0" value="classpath:internal.properties"/>
</bean>
<!-- Bean DAO -->
<bean abstract="true" id="abstractDao">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean class="fr.web.dao.AbsenceDao" id="absenceDao" parent="abstractDao"/>
</bean>
</beans>
property jobClass requires class and you have given reference of bean , So change
<bean id="exampleJob1" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" ref="jobClass" />
<property name="jobDataAsMap">
<map>
<entry key="timeout" value="5" />
</map>
</property>
</bean>
to (Note : value attribute below)
<bean id="exampleJob1" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="fr.acensi.web.utils.ExampleJob" />
<property name="jobDataAsMap">
<map>
<entry key="timeout" value="5" />
</map>
</property>
</bean>
There is another option here which you may think neater or not, I like it as it keeps the context a bit cleaner.
<bean id="exampleJob1" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
<bean factory-bean="jobClass" factory-method="getClass" />
</property>
</bean>
the breakdown of the problem is as Jigar Joshi describes solution is slighty different.
It allows you to keep you bean jobClass instantiation seperate from the building of the JobDetailbean.