1

I've configured quartz job in jHipster server and it is working fine for System.out.println statement but when I try to use persistence related work It's giving me an exception. I've @Autowire JdbcTemplate jdbcTemplate; but it's still null and the reason is when the jHipster server runs it tells that :

 Scheduler meta-data: Quartz Scheduler (v2.2.1) 'schedulerFactoryBean' with instanceId **'NON_CLUSTERED'**
  Scheduler class: 'org.quartz.core.QuartzScheduler' - **running locally**.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - **which does not support persistence. and is not clustered**.

2017-09-26 10:56:10.523  INFO 10188 --- [  restartedMain] org.quartz.impl.StdSchedulerFactory      : Quartz scheduler **'schedulerFactoryBean' initialized from an externally provided properties** instance.
2017-09-26 10:56:10.523  INFO 10188 --- [  restartedMain] org.quartz.impl.StdSchedulerFactory      : Quartz scheduler version: 2.2.1
2017-09-26 10:56:10.523  INFO 10188 --- [  restartedMain] org.quartz.core.QuartzScheduler          : JobFactory set to: org.springframework.scheduling.quartz

These are the logs that jhipster prints and please tell how can I use persistence with jdbcTemplet I do not want open a separate JDBC connection. If possible I would like to use the existing service class but that also gives an error.

Here are my configuration file and job file

@Configuration
@ComponentScan("com.jobs")
public class QuartzJobSchedulerConf {
//http://www.concretepage.com/spring-4/spring-4-quartz-2-scheduler integration-annotation-example-using-javaconfig
//todo make common function for simple jobs to set attributes
//todo make common function for complex jobs to set attributes

    @Bean //this is simple job1
public MethodInvokingJobDetailFactoryBean methodInvokingJobDetailFactoryBean() {
    MethodInvokingJobDetailFactoryBean obj = new MethodInvokingJobDetailFactoryBean();
    obj.setTargetBeanName("jobone");
    obj.setTargetMethod("myTask");
    return obj;
}
@Bean
public SimpleTriggerFactoryBean simpleTriggerFactoryBean(){
    //This trigger will schedule the job after 3 seconds and repeat after every 30 seconds for 3+1 times.
    SimpleTriggerFactoryBean stFactory = new SimpleTriggerFactoryBean();
    stFactory.setJobDetail(methodInvokingJobDetailFactoryBean().getObject());
    stFactory.setStartDelay(3000);
    stFactory.setRepeatInterval(30000);
    stFactory.setRepeatCount(3);//todo repeat counter remove or use
    return stFactory;
}

@Bean //this is simple job2
public MethodInvokingJobDetailFactoryBean methodInvokingJobDetailFactoryBean2() {
    MethodInvokingJobDetailFactoryBean obj = new MethodInvokingJobDetailFactoryBean();
    obj.setTargetBeanName("jobtwo");
    obj.setTargetMethod("myTask");
    return obj;
}
@Bean
public SimpleTriggerFactoryBean simpleTriggerFactoryBean2(){
    SimpleTriggerFactoryBean stFactory = new SimpleTriggerFactoryBean();
    stFactory.setJobDetail(methodInvokingJobDetailFactoryBean2().getObject());
    stFactory.setStartDelay(3000);
    stFactory.setRepeatInterval(30000);
    stFactory.setRepeatCount(3);//todo repeat counter remove or use
    return stFactory;
}
@Bean//this is complex job1
public JobDetailFactoryBean jobDetailFactoryBean(){
    /*To pass the parameter to job by JavaConfig, we can have setter method and
    the property should be configured with setJobDataAsMap() in JobDetailFactoryBean
     configuration in JavaConfig*/
    JobDetailFactoryBean factory = new JobDetailFactoryBean();
    factory.setJobClass(SampleComplexJob.class);
    Map<String,Object> map = new HashMap<String,Object>();
    map.put("name", "RAM");
    map.put(SampleComplexJob.COUNT, 1);
    factory.setJobDataAsMap(map);
    factory.setGroup("mygroup");
    factory.setName("myjob");
    return factory;
}
@Bean
public CronTriggerFactoryBean cronTriggerFactoryBean(){
    CronTriggerFactoryBean stFactory = new CronTriggerFactoryBean();
    stFactory.setJobDetail(jobDetailFactoryBean().getObject());
    stFactory.setStartDelay(3000);
    stFactory.setName("mytrigger");
    stFactory.setGroup("mygroup");
    stFactory.setCronExpression("0 0/1 * 1/1 * ? *");
    return stFactory;
}

@Bean
public SchedulerFactoryBean schedulerFactoryBean() {
    SchedulerFactoryBean scheduler = new SchedulerFactoryBean();
    scheduler.setTriggers(simpleTriggerFactoryBean().getObject(),
        simpleTriggerFactoryBean2().getObject(),
        cronTriggerFactoryBean().getObject());
    return scheduler;
}
}

There is the job Class code

/*If we want to persist the changes in JobDataMap, we will annotate our class by @PersistJobDataAfterExecution */
@PersistJobDataAfterExecution

/*if there is more than one trigger which are scheduling same job then to avoid race condition, we have to annotate our job with @DisallowConcurrentExecution.*/
@DisallowConcurrentExecution

public class SampleComplexJob extends QuartzJobBean {

@Autowired
JdbcTemplate jdbcTemplate;

public static final String COUNT = "count";
private String name;
protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {

    for(String role:findRoleByPrivilegeSQLExample("PRIV_USER_SETTING")){
        System.out.println(role);
    }
    JobDataMap dataMap = ctx.getJobDetail().getJobDataMap();
    int cnt = dataMap.getInt(COUNT);
    JobKey jobKey = ctx.getJobDetail().getKey();
    System.out.println(jobKey+": "+name+": "+ cnt);
    cnt++;
    dataMap.put(COUNT, cnt);
}
public void setName(String name) {
    this.name = name;
}

public List<String> findRoleByPrivilegeSQLExample(String privilege){

    ///this is SQL example
    List<String> rolePrivilegesList = new ArrayList<String>();
    if(!privilege.isEmpty()){
        StringBuilder sql=new StringBuilder()
            .append("SELECT ID_ROLE FROM ROLE_PRIVILEGES WHERE ")
            .append("UPPER(ID_PRIVILEGE) = '")
            .append(privilege.toUpperCase()).append("'");
        rolePrivilegesList = jdbcTemplate.queryForList(sql.toString(),String.class);
    }
    return rolePrivilegesList;
}
}

If there is another way to configure Quartz job in jHipster please tell me. Or if jHipster gives out of the box functionality for Scheduler work then It would be great.

Quartz job Dependency

<dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>2.2.1</version>
    </dependency>
Patrick
  • 12,336
  • 15
  • 73
  • 115
NewCoder
  • 81
  • 2
  • 11
  • show the exception which is thrown. – Patrick Sep 26 '17 at 09:26
  • @Patrick thank you for replying. It's a null pointer exception for JdbcTemplate. – NewCoder Sep 26 '17 at 09:47
  • **Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.** I do not know why jHipster is printing this log while starting Quartz scheduler. – NewCoder Sep 26 '17 at 09:50
  • its not jhipster its the job itself and its just a info for you nothing else – Patrick Sep 26 '17 at 11:25
  • Think the NPE is because JdbcTemplate is not getting injected. take a look at https://stackoverflow.com/questions/37075328/nullpointerexception-while-deploying-quartz-in-spring-boot/37086715#37086715 – Srinivas Sep 26 '17 at 23:03
  • thank you for replying its resolve.. actually, I was not configuring it correctly. – NewCoder Sep 27 '17 at 06:40

1 Answers1

0

1) Why my bean was not being autoconfigured was because it not configuring correctly.

Updated class QuartzJobSchedulerConf.java

@Configuration
@ComponentScan("com.jobs")
public class QuartzJobSchedulerConf {

 @Bean//this is complex job1
public JobDetailFactoryBean jobDetailFactoryBean(ComplexJobService complexJobService){

    JobDetailFactoryBean factory = new JobDetailFactoryBean();
    factory.setJobClass(ComplexScheduledJob.class);
    Map<String,Object> map = new HashMap<String,Object>();
    map.put("complexJobService", complexJobService);
    factory.setJobDataAsMap(map);
    factory.setDurability(true);

    return factory;
}
@Bean
public CronTriggerFactoryBean cronTriggerFactoryBean(ComplexJobService complexJobService){

    CronTriggerFactoryBean stFactory = new CronTriggerFactoryBean();
    stFactory.setJobDetail(jobDetailFactoryBean(complexJobService).getObject());
    stFactory.setCronExpression("0 0/1 * 1/1 * ? *");
    stFactory.setStartDelay(3000);

    return stFactory;
}

@Bean
public SchedulerFactoryBean schedulerFactoryBean(ComplexJobService complexJobService) {

    SchedulerFactoryBean scheduler = new SchedulerFactoryBean();
    scheduler.setConfigLocation(new ClassPathResource("properties/quartz.properties"));
    scheduler.setTriggers(
        cronTriggerFactoryBean(complexJobService).getObject());
    return scheduler;
    }
}

Added Classes ComplexJobService.java

@Component("complexJobService")
public class ComplexJobService {

@Autowired
JdbcTemplate jdbcTemplate;

@Autowired
UtilityService utilityService;

protected void execute() {

//        utilityService.fetchCountriesDTO();

}
}

ComplexScheduledJob.java

@PersistJobDataAfterExecution
@DisallowConcurrentExecution
@Component
public class ComplexScheduledJob extends QuartzJobBean{

@Autowired
private ComplexJobService complexJobService;
private static int count;

@Override
protected void executeInternal(JobExecutionContext jobContext)
        throws JobExecutionException {

    complexJobService.execute();
    count++;
    System.out.println("Job count " + count);
}

public void setComplexJobService(ComplexJobService complexJobService) {
    this.complexJobService = complexJobService;
}
}

This java configuration replaces the XML configuration of Quartz Scheduler e.g.

<bean name="complexJobDetail"    class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
    <property name="jobClass" value="com.jobs.ComplexScheduledJo" />
    <property name="jobDataMap">
        <map>
            <entry key="complexJobService" value-ref="complexJobService" />
        </map>
    </property>
    <property name="durability" value="true" />
</bean>
NewCoder
  • 81
  • 2
  • 11
  • You can download the quartz.properties file from anywhere – NewCoder Sep 27 '17 at 07:09
  • To learn basic about [Quartz Job Scheduler Tutorial](https://examples.javacodegeeks.com/enterprise-java/quartz/quartz-scheduler-properties-example/) – NewCoder Sep 27 '17 at 07:10