Announcement Announcement Module
Collapse
No announcement yet.
Spring @Scheduled: problems in getting cron expression from properties file Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring @Scheduled: problems in getting cron expression from properties file

    Hi all

    First of all I wish you and your beloved all the best for this Christmass and a wonderful happy new year

    Now...In my project I'm using spring 3.1.1 and I need to execute some scheduled jobs
    I used spring-batch for the job stuffs then I used the spring's @Scheduled annotation in order to execute them and all works pretty good
    Next step is that I want to configure the @Scheduled cron expression in a properties file and I'm having some problems

    The project is composed by several sub-modules; each sub-module is a separate maven artifact (and, obviously, a separate eclipse project)
    So in my case I have a sub-module where I configure the propertyplaceholder (taking inspiration by this link http://forum.springsource.org/showth...ron-expression)
    Now in this sub-module I have this configuration:
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p"
    	xmlns="http://www.springframework.org/schema/beans" 
        xmlns:task="http://www.springframework.org/schema/task"
        xmlns:batch="http://www.springframework.org/schema/batch"
    	xsi:schemaLocation="http://www.springframework.org/schema/aop 
                            http://www.springframework.org/schema/aop/spring-aop.xsd
    		                http://www.springframework.org/schema/beans 
                            http://www.springframework.org/schema/beans/spring-beans.xsd
    		                http://www.springframework.org/schema/tx 
                            http://www.springframework.org/schema/tx/spring-tx.xsd
    		                http://www.springframework.org/schema/context 
                            http://www.springframework.org/schema/context/spring-context.xsd 
                            http://www.springframework.org/schema/task 
                            http://www.springframework.org/schema/task/spring-task.xsd 
                            http://www.springframework.org/schema/batch
                            http://www.springframework.org/schema/batch/spring-batch.xsd">
                            
    	<context:annotation-config />
    	<tx:annotation-driven transaction-manager="jtaTransactionManager" />
        <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
            <property name="ignoreResourceNotFound" value="false"/>
            <property name="locations">
                <list>
                    <value>classpath:subModuleASchduledCron.properties</value>
                </list>
            </property>
        </bean>
        <aop:aspectj-autoproxy />
    </beans>
    In another project i have a configuration file with this content:

    Code:
    scheduledCronExpre=15 0 0 * * *
    In my class I have:

    Code:
    @Scheduled(cron = "${scheduledCronExpre}")	
    public void doJob(){
    //do my stuffs
    }
    Well when I try to execute this code I get this error:
    Code:
    Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'scheduledCronExpre'
    The full stacktrace is:
    Code:
    09:52:51,653 ERROR [StartMktIntelligenceBatches] Errore: Error creating bean with name 'myScheduledBean' defined in file [/dati/workspaces/indigo/SubModuleA/target/classes/it/schedulers/MyScheduledBean.class]: Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'scheduledCronExpre'
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myScheduledBean' defined in file [/dati/workspaces/indigo/SubModuleA/target/classes/it/schedulers/MyScheduledBean.class]: Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'scheduledCronExpre'
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
    	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:585)
    	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)
    	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
    	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:93)
    	at it.poste.crs.invimall.marketing.intelligent.mktintelligence.batch.main.StartMktIntelligenceBatches.main(StartMktIntelligenceBatches.java:26)
    Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'scheduledCronExpre'
    	at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:173)
    	at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:125)
    	at org.springframework.beans.factory.config.PropertyPlaceholderConfigurer$PlaceholderResolvingStringValueResolver.resolveStringValue(PropertyPlaceholderConfigurer.java:255)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:748)
    	at org.springframework.context.support.ApplicationContextAwareProcessor$EmbeddedValueResolver.resolveStringValue(ApplicationContextAwareProcessor.java:136)
    	at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor$1.doWith(ScheduledAnnotationBeanPostProcessor.java:145)
    	at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:473)
    	at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:451)
    	at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.postProcessAfterInitialization(ScheduledAnnotationBeanPostProcessor.java:114)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:407)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1461)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
    	... 11 more
    By debugging I see that, when the spring context is loaded, the properties file is read by Spring....but then when I try to use a property of this property file the properties stored by the spring context seem to be null....
    I tried to search in all my projects if there was another declaration of PropertyPlaceholderConfigurer but I didn't find it...and this problem is killing me...
    Do you have any idead on how I can solve this issue?

    Thank you
    Angelo

  • #2
    Hi all

    Any Idea on how I can solve this issue? I'm still fighting with this issue..and the winner is the issue

    Comment


    • #3
      Make sure the file containing the properties is loaded. Also really make sure that there is no other PropertyPlaceHolderConfigurer configured (or a <contextroperty-placeholder/>) element. Also make sure that all your applicationcontext files are loaded in the same application context.

      Also for loading from different jar files use classpath*: instead of classpath:.

      Comment


      • #4
        Hi Marten

        Thank you for the answer
        I checked what you said
        The property file is loaded (moreover by debugging the spring context loading I arrived in the point where I can see that the file is loaded and properties are stored) and I have no other ApplicationContext starting. In fact I'm using a main class where I use a ClassPathXmlApplicationContext in order to load all the involved XML spring files. Its code is the following one:

        Code:
        ....
        public class StartBatches {
        	private static final Log logger = LogFactory.getLog(StartBatches.class.getName());
        	public static void main (String[] args) throws Exception{
        		try {
        			//Indico i file di contesto di spring da caricare
        			String[] springCtxFiles = {"moduleAAppCtx.xml","moduleBAppCtx.xml", "moduleCAppCtx.xml"};
        			//Carico il contesto di spring
        			ApplicationContext ctx = new ClassPathXmlApplicationContext(springCtxFiles);
        		} catch (Exception e) {
        			
        			logger.fatal("Errore durante la partenza dei batch; messaggio errore: "+e.getMessage(), e);
                                throw e;
        		}
        	}
        }
        When I execute the early written main the properties file is loaded only once and it seems to me the Spring classes, involved in loading the properties file, are no more called during the Spring context loading.

        I checked that there is no other PropertyPlaHolderConfigurer (and/or <contexrtroperty-placeholder />) element
        I also used classpath*: instead of classpath: but.....nothing changed .... It's so frustrating

        Any other tip I can follow?
        Thank you
        Angelo
        Last edited by angeloimm; Jan 4th, 2013, 03:52 AM.

        Comment


        • #5
          Replace the propertyplaceholder with contextroperty-placeholder see if that changes anything. Switching the order of yuor context files might also help.

          Comment


          • #6
            Hello Marten

            I tried as you suggested by using contextroperty-placeholder
            In detail this is my spring context file:
            Code:
            <?xml version="1.0" encoding="UTF-8"?>
            <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
            	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p"
            	xmlns="http://www.springframework.org/schema/beans" 
                xmlns:task="http://www.springframework.org/schema/task"
                xmlns:batch="http://www.springframework.org/schema/batch"
            	xsi:schemaLocation="http://www.springframework.org/schema/aop 
                                    http://www.springframework.org/schema/aop/spring-aop.xsd
            		                http://www.springframework.org/schema/beans 
                                    http://www.springframework.org/schema/beans/spring-beans.xsd
            		                http://www.springframework.org/schema/tx 
                                    http://www.springframework.org/schema/tx/spring-tx.xsd
            		                http://www.springframework.org/schema/context 
                                    http://www.springframework.org/schema/context/spring-context-3.0.xsd 
                                    http://www.springframework.org/schema/task 
                                    http://www.springframework.org/schema/task/spring-task.xsd 
                                    http://www.springframework.org/schema/batch
                                    http://www.springframework.org/schema/batch/spring-batch.xsd">
                                    
            	<context:annotation-config />
            	<tx:annotation-driven transaction-manager="inViMallJtaTransactionManager" />
                <context:property-placeholder ignore-resource-not-found="false" location="classpath*:myProperties.properties"/>
                 <bean id="sqlDV" class="org.mybatis.spring.SqlSessionFactoryBean" >
                    <property name="dataSource" ref="dataSourceDV" />
                </bean>
                <bean id="myBatisAutoScanDV" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
                    <property name="basePackage" value="it.common.dao" />
                    <property name="sqlSessionFactory" ref="sqlDV" />
                </bean>
                <aop:aspectj-autoproxy />
            </beans>
            But I still have the error....this is making me really crazy....Any other tip I can use?

            Angelo

            Comment


            • #7
              Hello

              I tried in using the contextlaceholder but nothing changed
              I debugged the code and I see that the properties file is loaded in the class "org.springframework.core.io.support.PropertiesLoad erSupport"
              But then in no place there is an instruction like "System.setProperties....."; as far as I know (but I may be wrong) this means that in the class "org.springframework.beans.factory.config.Property PlaceholderConfigurer" when we try to execute the method "resolveSystemProperty" the obtained value will be always null since the method implementation is:
              Code:
              	protected String resolveSystemProperty(String key) {
              		try {
              			String value = System.getProperty(key);
              			if (value == null && this.searchSystemEnvironment) {
              				value = System.getenv(key);
              			}
              			return value;
              		}
              		catch (Throwable ex) {
              			if (logger.isDebugEnabled()) {
              				logger.debug("Could not access system property '" + key + "': " + ex);
              			}
              			return null;
              		}
              	}
              Am I missing anything?
              I really can't figure where I'm wrong.....
              I did a very simple thing...I modified my main class in this way:
              Code:
              ....
              public class StartBatches {
              	private static final Log logger = LogFactory.getLog(StartBatches.class.getName());
              	public static void main (String[] args) throws Exception{
              		try {
                                      Resource prop = new ClassPathResource("subModuleASchduledCron.properties");
                                      Properties props = new Properties();
              			props.load(prop.getInputStream());
              			Enumeration<Object> chiavi = props.keys();
              			while (chiavi.hasMoreElements()) {
              				Object object = (Object) chiavi.nextElement();
              				System.getProperties().setProperty((String)object, (String)props.get(object));
              			}
              			//Indico i file di contesto di spring da caricare
              			String[] springCtxFiles = {"moduleAAppCtx.xml","moduleBAppCtx.xml", "moduleCAppCtx.xml"};
              			//Carico il contesto di spring
              			ApplicationContext ctx = new ClassPathXmlApplicationContext(springCtxFiles);
              		} catch (Exception e) {
              			
              			logger.fatal("Errore durante la partenza dei batch; messaggio errore: "+e.getMessage(), e);
                                      throw e;
              		}
              	}
              }
              Let's not see code quality...by doing this thing all works pretty good....
              I'm wondering.....is this correct? Am I doing anything wrong?

              Any suggestion is really welcome....
              Thank you
              Angelo

              Comment


              • #8
                What is wrong with System.setProperty or System.setProperties ? (I strongly suggest the API docs).

                Also not sure what you are trying here at least why you are so focussed on the resolveSystemProperty method as your stacktrace indicates that there is no mention of that method being called. The PropertyPlaceHolder will never set system properties but will/can use that as a fallback/override to loaded properties files.

                Put a break point in the postProcessBeanFactory method of the PropertyResourceConfigurer class and see if that executes before your annotation gets parsed. If that is the case the properties should be available if not the properties aren't available and you have an ordering issue (as mentioned earlier).

                Comment


                • #9
                  Hi Marten

                  My intention was not to say that there is something wrong with System.setProperty or System.setProperties (and sure I see the API docs) and I absolutly don't want to attack anyone...I'm only trying to understand where I'm wrong (because I'm pretty sure that it's something related to my configuration) and it seems to me strange that, even if the property file is loaded, the properties are not available.
                  So if I gave the sensation I wanted to attack..please pardon me

                  With regards to the break point in the postProcessBeanFactory method of the PropertyResourceConfigurer class...I have set it and it seems to me that this method is called before that my annotation is called (sure you are talking of the @Scheduled annotation); in fact I enter in the break point before that the batch is tried to be executed and, as I said, in the java.util.Properties object passed between the several classes my properties are present; when I try to get one of them...I get a null value.

                  Regarding the ordering issue I followed this approach:
                  • the first file is where my jta transaction manager is defined
                  • the second file is where the PropertyPlaceholderConfigurer is defined
                  • the third file is where there is the batch I want to execute

                  Now I tried in this order:
                  • the second file is where the PropertyPlaceholderConfigurer is defined
                  • the first file is where my jta transaction manager is defined
                  • the third file is where there is the batch I want to execute

                  And now It seems to work.....Thank you for the support....the problem is related to the ordering...

                  Cheers,

                  Angelo
                  Last edited by angeloimm; Jan 7th, 2013, 06:30 AM.

                  Comment


                  • #10
                    With regards to the break point in the postProcessBeanFactory method of the PropertyResourceConfigurer class...I have set it and it seems to me that this method is called before that my annotation is called (sure you are talking of the @Scheduled annotation); in fact I enter in the break point before that the batch is tried to be executed and, as I said, in the java.util.Properties object passed between the several classes my properties are present; when I try to get one of them...I get a null value.
                    Indeed at leat the postProcessBeanFactory method of the PRC should execute before the method parsing the @Scheduled annotation.

                    However the fact that ordering is important is still a bit strange as the PropertyPlaceHolderConfigurer is a BeanFactoryPostProcessor which operates before any other postprocessors. The BeanPostProcessor should execute after that.

                    The only thing I can imagine is that the BeanPostProcessor somehow gets it dependencies injected before all the BeanFactoryPostProcessors have executed or at least have influenced the EmbeddedValueResolver.

                    Would it be possible for you to create a small testcase showing this probably a contextroperty-placeholder and task:annotation-driven would be enough to show this issue. When done could you register a JIRA issue...

                    Comment


                    • #11
                      Originally posted by Marten Deinum View Post
                      Would it be possible for you to create a small testcase showing this probably a contextroperty-placeholder and task:annotation-driven would be enough to show this issue. When done could you register a JIRA issue...
                      Hello Marten
                      I'll provide this small testcase ASAP
                      Angelo

                      Comment


                      • #12
                        Hello Marten

                        I prepared this little sample: three vary basic projects:
                        • JTA configuration
                        • PropertyPlaceHolder set-up
                        • Batch configuration

                        I don't know why...in this case the context file order is not important
                        In the previous, and more complex project, the order matters... I don't know the reason

                        I don't know if this is usefull...anyway I attach to the post the created simple project. It's a very simple maven project. I'll not open a Jira issue

                        Regards,
                        Angelo

                        Comment

                        Working...
                        X