Announcement Announcement Module
Collapse
No announcement yet.
Spring + Quartz 2.1.x in an OSGi environment problem with SimpleTriggerFactoryBean Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring + Quartz 2.1.x in an OSGi environment problem with SimpleTriggerFactoryBean

    I am trying to migrate to use Spring with Quartz 2.0 on the Apache Karaf OSGi environment. I am having trouble using the SimpleTriggerFactoryBean as it tries to instantiate org.quartz.SimpleTrigger (an interface in Quartz 2.x)

    Through the debugger, I have determined that the following line in the SpringTriggerFactoryBean.java

    simpleTriggerClass = getClass().getClassLoader().loadClass("org.quartz. impl.triggers.SimpleTriggerImpl");

    will throw a ClassNotFoundException and make it default to instantiate SimpleTrigger.

    I have confirmed that "org.quartz.impl.triggers" is in the Import-Packages. I have modified an existing code in the package to perform a System.out.println(new SimpleTriggerImpl()) and that works successfully and I have also tried using DynamicImport-Package = * with no luck.

    Full stack trace below:
    Code:
    Exception in thread "SpringOsgiExtenderThread-70" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'healthCheckManagerTrigger' defined in URL [bundleentry://235.fwk1084573260/META-INF/spring/module-context.xml]: Invocation of init method failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.quartz.SimpleTrigger]: Specified class is an interface
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1455)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
    	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:591)
    	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
    	at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.access$1600(AbstractDelegatedExecutionApplicationContext.java:69)
    	at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext$4.run(AbstractDelegatedExecutionApplicationContext.java:355)
    	at org.springframework.osgi.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85)
    	at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.completeRefresh(AbstractDelegatedExecutionApplicationContext.java:320)
    	at org.springframework.osgi.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor$CompleteRefreshTask.run(DependencyWaiterApplicationContextExecutor.java:132)
    	at java.lang.Thread.run(Thread.java:722)
    Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.quartz.SimpleTrigger]: Specified class is an interface
    	at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:101)
    	at org.springframework.beans.BeanWrapperImpl.<init>(BeanWrapperImpl.java:163)
    	at org.springframework.scheduling.quartz.SimpleTriggerFactoryBean.afterPropertiesSet(SimpleTriggerFactoryBean.java:247)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
    	... 14 more

  • #2
    One way of getting around this that I got working was to create my own version of the FactoryBean but implement it so that it has the Quartz 2.x classes used in compilation.

    Another thing to note is when you are scheduling a trigger, make sure to expose the fact that the trigger is an "OperableTrigger" via the <interfaces> element otherwise it will say that the proxy class cannot be cast to OperableTrigger when scheduling a job.
    Last edited by trajano; Jul 31st, 2012, 08:59 AM.

    Comment


    • #3
      Originally posted by trajano View Post
      Through the debugger, I have determined that the following line in the SpringTriggerFactoryBean.java

      simpleTriggerClass = getClass().getClassLoader().loadClass("org.quartz. impl.triggers.SimpleTriggerImpl");

      will throw a ClassNotFoundException and make it default to instantiate SimpleTrigger.

      I have confirmed that "org.quartz.impl.triggers" is in the Import-Packages. I have modified an existing code in the package to perform a System.out.println(new SimpleTriggerImpl()) and that works successfully and I have also tried using DynamicImport-Package = * with no luck.
      The loadClass will use the classloader of the current class (getClass().getClassLoader()), which in this case is SpringTriggerFactoryBean. That means that the spring-context-support bundle must have the org.quartz.impl.triggers package listed as an import, and it does not. Looks like a bug in the Spring packaging caused because this class loading is done dynamically and therefore is not detected by Bundlor. The template.mf would have to be updated to import this class explicitly.

      You could try creating an empty subclass of SpringTriggerFactoryBean in your own bundle, which when used in the context should cause getClass().getClassLoader() to return the classloader of your bundle rather than the spring-context-support bundle.

      Comment

      Working...
      X