huahsin68 huahsin68 - 6 months ago 10
Java Question

How could I integrate Spring data source into Quartz?

I am trying to integrate the data source configure in Spring into Quartz scheduler. While I have gather few pieces of information from forums and mailing list on how this could be done, I am still not able to construct the whole piece.

I have the data source configure in Spring as following:

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/projectA"/>
<property name="lookupOnStartup" value="false"/>
<property name="cache" value="true"/>
<property name="proxyInterface" value="javax.sql.DataSource"/>
</bean>


And the Quartz-Spring configure like this:

<jee:jndi-lookup id="quartzDataSource"
lookup-on-startup="false"
proxy-interface="javax.sql.DataSource"
cache="true"
jndi-name="java:jdbc/projectA"/>

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
...

<property name="dataSource" ref="quartzDataSource"/>
</bean>


This is not the correct configuration as I got the following error:

[ERROR ] SRVE0283E: Exception caught while initializing context: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.scheduling.quartz.SchedulerFactoryBean#0' defined in class path resource [job-authentication-spring.xml]: Invocation of init method failed; nested exception is org.springframework.jndi.JndiLookupFailureException: JndiObjectTargetSource failed to obtain new target object; nested exception is javax.naming.InvalidNameException: java:jdbc/projectA
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1422)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:518)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:455)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:192)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:567)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:282)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:204)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
at com.ibm.ws.webcontainer.webapp.WebApp.notifyServletContextCreated(WebApp.java:1975)
at com.ibm.ws.webcontainer.webapp.WebApp.initialize(WebApp.java:748)
at com.ibm.ws.webcontainer.webapp.WebApp.initialize(WebApp.java:5694)
at com.ibm.ws.webcontainer.osgi.webapp.WebGroup.addWebApplication(WebGroup.java:84)
at com.ibm.ws.webcontainer.osgi.DynamicVirtualHost.addWebApplication(DynamicVirtualHost.java:150)
at com.ibm.ws.webcontainer.WebContainer.addWebApp(WebContainer.java:571)
at com.ibm.ws.webcontainer.WebContainer.addWebApplication(WebContainer.java:521)
at com.ibm.ws.webcontainer.osgi.WebContainer.addWebContainerApplication(WebContainer.java:649)
at com.ibm.ws.app.manager.war.internal.WARApplicationHandler.install(WARApplicationHandler.java:153)
at com.ibm.ws.app.manager.internal.statemachine.StartAction.execute(StartAction.java:145)
at com.ibm.ws.app.manager.internal.statemachine.ApplicationStateMachine.changeState(ApplicationStateMachine.java:358)
at com.ibm.ws.app.manager.internal.statemachine.ApplicationStateMachine.changeState(ApplicationStateMachine.java:248)
at com.ibm.ws.app.manager.internal.statemachine.ApplicationStateMachine$StateChangeCallback.processChange(ApplicationStateMachine.java:138)
at com.ibm.ws.app.manager.internal.statemachine.ApplicationStateMachine$StateChangeCallback.changed(ApplicationStateMachine.java:120)
at com.ibm.ws.app.manager.internal.statemachine.LocateHandlerAction.arrived(LocateHandlerAction.java:91)
at com.ibm.ws.app.manager.internal.lifecycle.ReferenceMapHolder.addListener(ReferenceMapHolder.java:191)
at com.ibm.ws.app.manager.internal.statemachine.LocateHandlerAction.execute(LocateHandlerAction.java:65)
at com.ibm.ws.app.manager.internal.statemachine.ApplicationStateMachine.changeState(ApplicationStateMachine.java:358)
at com.ibm.ws.app.manager.internal.statemachine.ApplicationStateMachine.changeState(ApplicationStateMachine.java:248)
at com.ibm.ws.app.manager.internal.statemachine.ApplicationStateMachine$StateChangeCallback.processChange(ApplicationStateMachine.java:138)
at com.ibm.ws.app.manager.internal.statemachine.ApplicationStateMachine$StateChangeCallback.changed(ApplicationStateMachine.java:120)
at com.ibm.ws.app.manager.internal.statemachine.ApplicationStateMachine$ResourceCallback.succesfulCompletion(ApplicationStateMachine.java:154)
at com.ibm.ws.app.manager.internal.statemachine.ResolveFileAction.findFile(ResolveFileAction.java:95)
at com.ibm.ws.app.manager.internal.statemachine.ResolveFileAction.initComplete(ResolveFileAction.java:135)
at com.ibm.ws.kernel.filemonitor.internal.MonitorHolder.init(MonitorHolder.java:325)
at com.ibm.ws.kernel.filemonitor.internal.CoreServiceImpl.setMonitor(CoreServiceImpl.java:211)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.felix.scr.impl.helper.BaseMethod.invokeMethod(BaseMethod.java:227)
at org.apache.felix.scr.impl.helper.BaseMethod.access$500(BaseMethod.java:38)
at org.apache.felix.scr.impl.helper.BaseMethod$Resolved.invoke(BaseMethod.java:595)
at org.apache.felix.scr.impl.helper.BaseMethod.invoke(BaseMethod.java:476)
at org.apache.felix.scr.impl.manager.DependencyManager.invokeBindMethod(DependencyManager.java:1067)
at org.apache.felix.scr.impl.manager.DependencyManager.serviceAdded(DependencyManager.java:317)
at org.apache.felix.scr.impl.manager.DependencyManager.serviceChanged(DependencyManager.java:171)
at org.eclipse.osgi.internal.serviceregistry.FilteredServiceListener.serviceChanged(FilteredServiceListener.java:104)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.dispatchEvent(BundleContextImpl.java:861)
at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)
at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:148)
at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.publishServiceEventPrivileged(ServiceRegistry.java:819)
at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.publishServiceEvent(ServiceRegistry.java:771)
at org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl.register(ServiceRegistrationImpl.java:130)
at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.registerService(ServiceRegistry.java:214)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.registerService(BundleContextImpl.java:433)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.registerService(BundleContextImpl.java:451)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.registerService(BundleContextImpl.java:950)
at com.ibm.ws.app.manager.internal.lifecycle.ServiceReg.register(ServiceReg.java:89)
at com.ibm.ws.app.manager.internal.statemachine.ResolveFileAction.execute(ResolveFileAction.java:110)
at com.ibm.ws.app.manager.internal.statemachine.ApplicationStateMachine.changeState(ApplicationStateMachine.java:358)
at com.ibm.ws.app.manager.internal.statemachine.ApplicationStateMachine.changeState(ApplicationStateMachine.java:248)
at com.ibm.ws.app.manager.internal.statemachine.ApplicationStateMachine$StateChangeCallback.processChange(ApplicationStateMachine.java:138)
at com.ibm.ws.app.manager.internal.statemachine.ApplicationStateMachine$StateChangeCallback.changed(ApplicationStateMachine.java:120)
at com.ibm.ws.app.manager.internal.statemachine.StopAction$1.succesfulCompletion(StopAction.java:56)
at com.ibm.ws.app.manager.internal.statemachine.StopAction$1.succesfulCompletion(StopAction.java:52)
at com.ibm.ws.threading.internal.FutureMonitorImpl$FutureMonitorInfo.notifyListener(FutureMonitorImpl.java:49)
at com.ibm.ws.threading.internal.FutureMonitorImpl.onCompletion(FutureMonitorImpl.java:93)
at com.ibm.ws.app.manager.internal.statemachine.StopAction.execute(StopAction.java:52)
at com.ibm.ws.app.manager.internal.statemachine.ApplicationStateMachine.changeState(ApplicationStateMachine.java:358)
at com.ibm.ws.app.manager.internal.statemachine.ApplicationStateMachine.changeState(ApplicationStateMachine.java:248)
at com.ibm.ws.app.manager.internal.monitor.ApplicationMonitor$EventType.executeEvent(ApplicationMonitor.java:314)
at com.ibm.ws.app.manager.internal.monitor.ApplicationMonitor$ApplicationListeners.executeEvent(ApplicationMonitor.java:284)
at com.ibm.ws.app.manager.internal.monitor.ApplicationMonitor$ApplicationListeners.access$600(ApplicationMonitor.java:183)
at com.ibm.ws.app.manager.internal.monitor.ApplicationMonitor$ApplicationListeners$1.call(ApplicationMonitor.java:268)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:98)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:206)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: org.springframework.jndi.JndiLookupFailureException: JndiObjectTargetSource failed to obtain new target object; nested exception is javax.naming.InvalidNameException: java:jdbc/projectA
at org.springframework.jndi.JndiObjectTargetSource.getTarget(JndiObjectTargetSource.java:139)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:182)
at $Proxy20.getConnection(Unknown Source)
at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111)
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)
at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:280)
at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:320)
at org.springframework.scheduling.quartz.LocalDataSourceJobStore.initialize(LocalDataSourceJobStore.java:139)
at org.quartz.impl.StdSchedulerFactory.instantiate(StdSchedulerFactory.java:1318)
at org.quartz.impl.StdSchedulerFactory.getScheduler(StdSchedulerFactory.java:1509)
at org.springframework.scheduling.quartz.SchedulerFactoryBean.createScheduler(SchedulerFactoryBean.java:600)
at org.springframework.scheduling.quartz.SchedulerFactoryBean.afterPropertiesSet(SchedulerFactoryBean.java:481)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1479)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1419)
... 87 more
Caused by: javax.naming.InvalidNameException: java:jdbc/projectA
at com.ibm.ws.jndi.url.contexts.javacolon.internal.JavaURLName.<init>(JavaURLName.java:83)
at com.ibm.ws.jndi.url.contexts.javacolon.internal.JavaURLNameParser.parse(JavaURLNameParser.java:36)
at com.ibm.ws.jndi.url.contexts.javacolon.internal.JavaURLNameParser.parse(JavaURLNameParser.java:48)
at com.ibm.ws.jndi.url.contexts.javacolon.internal.JavaURLContext$NameUtil.<init>(JavaURLContext.java:458)
at com.ibm.ws.jndi.url.contexts.javacolon.internal.JavaURLContext.lookup(JavaURLContext.java:299)
at com.ibm.ws.jndi.url.contexts.javacolon.internal.JavaURLContext.lookup(JavaURLContext.java:354)
at org.apache.aries.jndi.DelegateContext.lookup(DelegateContext.java:161)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:154)
at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:87)
at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:152)
at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:178)
at org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:95)
at org.springframework.jndi.JndiObjectLocator.lookup(JndiObjectLocator.java:105)
at org.springframework.jndi.JndiObjectTargetSource.getTarget(JndiObjectTargetSource.java:132)
... 100 more


I wasn't sure what else is missing in this Spring configuration, hope you guys could share some light on this problem.

Answer

I am not sure why this issue is happening, but here is what I did this to get it working:

First I extended org.springframework.scheduling.quartz.SchedulerFactoryBean to create my own implementation MySchedulerFactoryBean.

Then this was wired in the spring context xml:

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="myDS" />
    <property name="annotatedClasses">
        <list>
 ... your list of orm classes 
       </list>
</property>
</bean>


<bean id="transactionManager"
    class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="myDS" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="${database.driverClassName}" />
    <property name="initialSize" value="${database.initialSize}" />
    <property name="maxActive" value="${database.maxActive}" />
    <property name="maxIdle" value="${database.maxIdle}" />
    <property name="testOnBorrow" value="true"/>
    <property name="testWhileIdle" value="false"/>
    <property name="validationQuery" value="${database.validationQuery}" />
</bean>


<bean id="myQuartzSchedFactoryBean" class="com.scheduler.MySchedulerFactoryBean"
    lazy-init="true" scope="prototype">
    <!-- This datasource is initially passed as the default one, but later set internally in the code -->
    <property name="dataSource" ref="myDS" />
    <property name="transactionManager" ref="transactionManager" />
    <property name="configLocation" value="classpath:META-INF/quartz.properties" />
    <property name="applicationContextSchedulerContextKey" value="applicationContext" />
    <property name="autoStartup" value="false" />
</bean>

Then where ever I want to schedule the job I get an instance of MySchedulerFactoryBean and use it like this

MySchedulerFactoryBean quartzSchedulerFactoryBean = //get the bean from spring
Scheduler scheduler = quartzSchedulerFactoryBean.getScheduler();
scheduler.schedule(...)

These are the quartz.properties entries:

org.quartz.scheduler.instanceName = MyScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 30
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.useProperties = false
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate

And I am using Quartz 2.1.2

Comments