0

I am trying to parameterize cron expression and reading it from properties file. During this process I get following exception "Error creating bean with name 'springScheduleCronExample': Initialization of bean failed; nested exception is java.lang.IllegalStateException: Encountered invalid @Scheduled method 'cronJob': Cron expression must consist of 6 fields (found 1 in "${cron.expression}")".

Then I found following post

Using that I cron expression is being read, only if I have

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( SpringScheduleCronExample.class);

define in my main method. The issue that I am having is, I want to run this on server without main method, can anyone please help me with this.

Here is my applicationContext.xml

<?xml  version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:task="http://www.springframework.org/schema/task"
 xmlns:util="http://www.springframework.org/schema/util"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">

    <task:annotation-driven />
    <util:properties id="applicationProps" location="application.properties" />
    <context:property-placeholder properties-ref="applicationProps"  />
    <bean class="com.hemal.spring.SpringScheduleCronExample" />
</beans>

My SpringScheduleCronExample.java looks like this

package com.hemal.spring;

import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

@Configuration
@EnableScheduling
@PropertySource("classpath:application.properties")
public class SpringScheduleCronExample {
    private AtomicInteger counter = new AtomicInteger(0);


    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {

        return new PropertySourcesPlaceholderConfigurer();
    } 

    @Scheduled(cron = "${cron.expression}")
    public void cronJob() {
        int jobId = counter.incrementAndGet();
        System.out.println("Job @ cron " + new Date() + ", jobId: " + jobId);
    }

    public static void main(String[] args) {

           AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
                   SpringScheduleCronExample.class);
        try {
            Thread.sleep(24000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
           context.close();
        }
    }
}

My application Properties has cron.expression=*/5 * * * * ?

Community
  • 1
  • 1
Hemal
  • 51
  • 1
  • 1
  • 5
  • do you know how to create a web app? If not, you can check first two steps from [this tutorial](https://www.mkyong.com/maven/how-to-create-a-web-application-project-with-maven/) for a simple example. If you have a web app you need to add spring dependencies to pom.xml and specify spring context in web.xml, for the latter check [this question](http://stackoverflow.com/questions/6451377/loading-context-in-spring-using-web-xml). – mczerwi Apr 30 '17 at 21:01
  • Czerwinski, I do know how to create a web app. My application does not have a GUI, it processes messages via MDB and make a web service call. If there are failures in web service call, rather then having an error queue to process these messages again, I want to have a spring scheduler to run every 4 hours which mill make web service call. I have this process working. I want to move the cron expression to a properties file and facing challenges in this process. – Hemal Apr 30 '17 at 23:43
  • I still don't exactly understand what problems are you facing. Are your `applicationContext.xml` and `application.properties` files on the classpath when you run the app on the server? If they are and the context is instantiated correctly (look at the last link in the first comment), then your scheduler should work just fine. – mczerwi May 01 '17 at 08:19
  • The issue was with context not being instantiated correctly. I modified my code accordingly and it works. I will post updated code. – Hemal May 01 '17 at 17:03

1 Answers1

1

Here is how I got it to work

Application-context.xml

<?xml  version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:task="http://www.springframework.org/schema/task"
 xmlns:util="http://www.springframework.org/schema/util"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">


    <context:property-placeholder properties-ref="applicationProps"  />
    <context:annotation-config/>
    <context:component-scan base-package="com.hemal.spring" />
    <task:annotation-driven />
</beans>

MyApplicationConfig.java

package com.hemal.spring;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.annotation.EnableScheduling;

@Configuration
@EnableScheduling
@ComponentScan(basePackages = {"com.hemal.spring"})
@PropertySource("classpath:application.properties")
public class MyApplicationConfig {

    @Bean
    public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        PropertySourcesPlaceholderConfigurer properties = new PropertySourcesPlaceholderConfigurer();

        properties.setLocation(new ClassPathResource( "application.properties" ));
        properties.setIgnoreResourceNotFound(false);

        return properties;
    }
}

MyApplicationContext.java

package com.hemal.spring;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;

public class MyApplicationContext implements WebApplicationInitializer{

    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(MyApplicationConfig.class);


        servletContext.addListener(new ContextLoaderListener(rootContext));
    }
}

My scheduler class

package com.hemal.spring;

import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;


public class SpringScheduleCronExample {
    private AtomicInteger counter = new AtomicInteger(0);

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {

        return new PropertySourcesPlaceholderConfigurer();
    } 

    @Scheduled(cron = "${cron.expression}")
    public void cronJob() {
        int jobId = counter.incrementAndGet();
        System.out.println("Job @ cron " + new Date() + ", jobId: " + jobId);
    }

    public static void main(String[] args) {
           AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
                   SpringScheduleCronExample.class);
        try {
            Thread.sleep(24000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
           context.close();
        }
    }
}

application.properties cron.expression=0/5 * * * * ?

Hemal
  • 51
  • 1
  • 1
  • 5