0

My requirement is to start the jobs during the weblogic server startup using the spring scheduler (ThreadpoolScheduler). Here is what i have done.

Created the Scheduler in app-context.xml-

task:scheduler id="scheduler" pool-size="10"

Created a method in a class that gets the Scheduler from the application context.xml during the @PostConstruct

@DependsOn("scheduler")
@PostConstruct
public void bootstrapJobs(){
    ScheduleTask1 task = (ScheduleTask1) instanceOf(Class.forName(jobInfo.getTaskClass()));
    task.setInstance(jobInfo.getJobName());
    CronTrigger trigger=new CronTrigger(jobInfo.getJobFrequency());
    ThreadPoolTaskScheduler scheduler = (ThreadPoolTaskScheduler)
        ApplicationContextProvider.getApplicationContext().getBean("scheduler");
    scheduler.schedule(task, trigger);
}

This is scheduling jobs perfectly fine on my local weblogic server, but on production it gives me the below exception at the line... (ThreadPoolTaskScheduler)

ApplicationContextProvider.getApplicationContext().getBean("scheduler");
scheduler.schedule(task, trigger).

Any idea on how to resolve this issue?

java.lang.NullPointerException
        at SchedulerService.createJob(SchedulerService.java:67) [_wl_cls_gen.jar:?]
        at SchedulerService.createBootstrapJob(SchedulerService.java:121) [_wl_cls_gen.jar:?]
        at SchedulerService.bootstrapJobs(SchedulerService.java:91) [_wl_cls_gen.jar:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_15]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[?:1.7.0_15]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.7.0_15]
        at java.lang.reflect.Method.invoke(Method.java:601) ~[?:1.7.0_15]
M. Deinum
  • 115,695
  • 22
  • 220
  • 224
ram
  • 173
  • 2
  • 4
  • 13
  • Why are you scheduling jobs yourself, why not let spring do that for you using the task namespace? Or the `@Scheduled` annotation. – M. Deinum Dec 15 '14 at 08:23
  • @M.Denim- I have the specific requirement.. where in i have to create the jobs dynamically on different tasks... tasks would increase drastically... and the cron trigger will have to vary for each task... I am reading these taks and cron details from the Database and creating the jobs... – ram Dec 15 '14 at 08:27
  • Doing that in a `@PostConstruct` annotated method isn't the best way imho. Nor that you depend on a `ThreadPollTaskScheduler` you should depend on the `TaskScheduler` interface. That way you could get a WebLogic managed `TaskScheduler` instead of managing your own threads (which is basically not allowed in a JEE container). Which Spring version are you on? – M. Deinum Dec 15 '14 at 08:32
  • @M.Denim- i am using the 4.1.1.RELEASE. I AM OKAY FOR USING THE SPRING SCHEDULER if it can help my scenario. Can you give an Example that can suffice my scenario..? like reading the jobs, cron info from DB after the APP-CONTEXT BEANS LOADED. – ram Dec 15 '14 at 08:38

1 Answers1

1

When you are on Spring 4.1 you can create a bean that implements the SmartInitializingSingleton interface. The method on this interface will be called after all singletons have been constructed.

public class SchedulerService implements SmartInitializingSingleton {

    @Autowired
    private TaskScheduler scheduler;

    public void afterSingletonsInstantiated() {
        ScheduleTask1 task = (ScheduleTask1) instanceOf(Class.forName(jobInfo.getTaskClass()));
        task.setInstance(jobInfo.getJobName());
        CronTrigger trigger=new CronTrigger(jobInfo.getJobFrequency());
        scheduler.schedule(task, trigger);
    }
}    

Oryou could implements the ApplicationListener interface and listen for ContextRefreshedEvents. The latter will be called after the application context is fully initialized.

Added benefit of both approaches is that you can simply inject the TaskScheduler instead of doing lookups yourself.

Now you are also constructing an instance of ScheduleTask1 yourself you might want to make this a prototype scoped bean and do a lookup using getBean on the BeanFactory. That way you can have your task dependencies injected, if that is needed.

public class SchedulerService implements SmartInitializingSingleton, BeanFactoryAware {

    @Autowired
    private TaskScheduler scheduler;

    private BeanFactory bf;

    public void afterSingletonsInstantiated() {
        ScheduleTask1 task = bf.getBean(jobInfo.getTaskClass);
        task.setInstance(jobInfo.getJobName());
        CronTrigger trigger=new CronTrigger(jobInfo.getJobFrequency());
        scheduler.schedule(task, trigger);
    }

    public void setBeanFactory(BeanFactory bf) {
        this.bf=bf;
    }
}

However to me it looks like you are trying to recreate facilities that are already provided by quartz and database driven jobs. So you might want to take a look at that also.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
  • Thanks for your valuable suggestion. SmartInitializingSingleton worked for me. database driven jobs from Qauartz may not work for my scenario since the database that i use do not have much support and drivers... Thanks for the help.. – ram Dec 15 '14 at 19:38