I am not an expert with Java and Springboot but I am building a QuartzScheduler application with JDBCStore in Spring Boot, I am using @Configuration, @Repository, @Service annotations for different classes in different packages, Structure has been given below.
The MySQL DataSource is available in Controller classes with @Autowired to DataSource (which is as Private) but where as if i try with the same Autowiring in other service classes, it is not working and it is throwing Null Pointer exception.
While the application loading, the DataSource is not available but later on when i am checking with @PostConstruct by printing the DataSource, it is showing up the HikariPool-1 DataSource.
Able to get the DataSource name in the SimpleCronScheduler through the RestController Get Method, Where as if i @Autowire the SimpleCronScheduler in TriggerListenerService, I cannot get the object and cannot use its Private methods like DataSource etc.
spring.datasource.url = jdbc:mysql://localhost/quartzscheduler?useSSL=false
spring.datasource.username = root
spring.datasource.password = password
spring.datasource.driverClassName= com.mysql.jdbc.Driver
spring.quartz.jdbc.initialize-schema=never
spring.jpa.show-sql=true
spring.datasource.tomcat.testOnBorrow=true
spring.datasource.tomcat.validationQuery=SELECT 1
spring.datasource.jmx-enabled=false
spring.jpa.hibernate.ddl-auto=none
spring.jpa.properties.hibernate.dialect =
org.hibernate.dialect.MySQL5InnoDBDialect
DataSource is null in main() method. The scope the DataSource is available in config and Controller packages but where as in services package, it is not reachable and Null.
I am really confused what i am missing here, please guide me if there is any programming concept i need to learn here to get the scope of the DataSource is available across the application, With the spring boot, it should be availbale by default but i am facing issue in which i am unable to use it as it is throwing Null Pointer Exception even after Auto configured.
Looking forward to hear your guidance and suggestions...
------main method file-----
package com.bsq.quartzscheduler;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
@ComponentScan
@EnableScheduling
@SpringBootApplication
@EnableAutoConfiguration
public class QuartzSchedulerPocApplication {
@Autowired
static DataSource dataSource;
public static void main(String[] args) {
SpringApplication.run(QuartzSchedulerPocApplication.class, args);
System.out.println(" ^^^^^^^^^^ DataSource Name: "+ dataSource);
}
}
-----------------Controller file----------
package com.bsq.quartzscheduler.controllers;
import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;
import static org.quartz.impl.matchers.EverythingMatcher.allJobs;
import static org.quartz.impl.matchers.EverythingMatcher.allTriggers;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import com.bsq.quartzscheduler.services.JobsListenerService;
import com.bsq.quartzscheduler.services.SampleJob;
import com.bsq.quartzscheduler.services.SampleJob2;
import com.bsq.quartzscheduler.services.SampleJob3;
import com.bsq.quartzscheduler.services.TriggerListenerService;
import java.io.IOException;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
@Controller
public class SimpleCronScheduler {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private JobsListenerService jobsListenerService;
@Autowired
private TriggerListenerService triggerListener;
@Autowired
private Scheduler sc;
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private DataSource dataSource;
@PostConstruct
public DataSource init() throws SchedulerException, IOException {
//sc = this.initiate();
logger.info("Hello from SimpleCronScheduler Controller... and DataSource is: "+ dataSource); //Outputs as HikariPool-1
return dataSource;
}
public void insertRecord() {
System.out.println(">>>>>>>DataSource : " + dataSource + "JDBC TEmplate: "+ jdbcTemplate);
String sql = "insert into qrtz_logtable (jobName, instance, createTime) values('BSQJ1', 'ANCE1','TIME')";
try {
System.out.println(">>>>>>>TRYING TO EXECUTE in insertRecord : " );
jdbcTemplate.update(sql);
} catch (Exception e) {
System.out.println(">>>>>>>exception in insertRecord : " + e.getLocalizedMessage());
}
}
@Bean
public Scheduler getScheduler() {
if ( sc == null ) {
try {
sc = StdSchedulerFactory.getDefaultScheduler();
sc.getListenerManager().addTriggerListener(triggerListener, allTriggers());
sc.getListenerManager().addJobListener(jobsListenerService, allJobs());
logger.info("Scheduler Name in getScheduler "+ sc.getSchedulerName());
} catch (SchedulerException e) {
logger.info("Exception in getScheduler method "+ e.getLocalizedMessage());
}
}
return sc;
}
@Bean
public String testMethod() {
logger.info( "Test Method Started "+dataSource);
return "TMS and DatSource Name--- "+dataSource; // Outputs as HikariPool-1 when i make a get call from RestController to this method.
}
public String startScheduler(Scheduler sc) {
try {
sc = getScheduler();
sc.start();
logger.info( "Scheduler name "+ sc.getSchedulerName()+" Started ");
return "Scheduler name "+ sc.getSchedulerName()+" Started ";
} catch (SchedulerException e) {
System.out.println("Start Scheduler exception "+ e.getMessage());
logger.info("EXCEPTION in Start Schduler "+ e.getMessage());
return "Failed to start Scheduler name "+ e.getMessage();
}
}
public String stopScheduler(){
try {
sc = getScheduler();
logger.info("Stopping Scheduler: "+ sc.getSchedulerName());
sc.standby();
logger.info("Keeping the scheduler in Standby "+ sc.getSchedulerName() );
return "Keeping the scheduler in Standby "+ sc.getSchedulerName();
} catch (SchedulerException e ) {
System.out.println("EXCEPTINO IN STOP SCHEDULER: "+ e.getMessage());
logger.info("EXCEPTION in stop Schduler "+ e.getMessage());
return "failed to Stop the the scheduler "+e.getMessage();
}
}
//Using CronTrigger to schedule the jobs
public String scheduleJobs(String jobName, int jobNum, String cronExpression, String groupName, String triggerName) {
System.out.println("Entered into Schedule Jobs");
JobDetail job = null;
CronTrigger trigger = null;
try {
sc = getScheduler();
if(jobNum==1) {
job = newJob(SampleJob.class).withIdentity(jobName, groupName).build();
} else if(jobNum ==2 ) {
job = newJob(SampleJob2.class).withIdentity(jobName, groupName).build();
} else {
job = newJob(SampleJob3.class).withIdentity(jobName, groupName).build();
}
// job = newJob(jobClass).withIdentity(jobName, groupName).build();
trigger = newTrigger().withIdentity(triggerName, groupName).withSchedule(cronSchedule(cronExpression)).build();
sc.getListenerManager().addTriggerListener(triggerListener, allTriggers());
sc.getListenerManager().addJobListener(jobsListenerService, allJobs());
sc.scheduleJob(job, trigger);
logger.info(job.getKey() + " has been scheduled to run at: " + " and repeat based on expression: "+ trigger.getCronExpression());
return "Job Added and scheduled for "+ jobName;
} catch (SchedulerException e) {
System.out.println("Failed to get Scheduler"+e.getMessage());
logger.info("Failed to get Scheduler "+ e.getMessage());
return "Failed to add JOb "+ e.getMessage();
}
}
public String runJob(String group, String jobName) {
try {
sc = getScheduler();
sc.triggerJob(new JobKey(jobName, group));
logger.info("Running the Job rightaway "+ group+"-"+jobName);
return "Triggered the Job to run now "+ group+"-"+jobName;
} catch (SchedulerException e ) {
System.out.println("EXCEPTINO IN RUN JOB : "+ e.getMessage());
logger.info("EXCEPTION in RUN JOB "+ e.getMessage());
return "Failed to run the job"+e.getMessage();
}
}
public String stopJob(String group, String jobName) {
try {
sc = getScheduler();
sc.interrupt(new JobKey(jobName, group));
logger.info("Stopping the Job rightaway "+ group+"-"+jobName);
return "Triggered the Job to run now "+ group+"-"+jobName;
} catch (SchedulerException e ) {
System.out.println("EXCEPTINO IN INTERRUPTION OF JOB : "+ e.getMessage());
logger.info("EXCEPTION INTERRUPTION OF JOB JOB "+ e.getMessage());
return "Failed to STOP the job"+e.getMessage();
}
}
public String deleteJob(String group, String name) {
try {
sc = getScheduler();
sc.deleteJob(new JobKey(name, group));
return "Job Deleted: "+ group+"-"+name;
} catch (SchedulerException e) {
return "Failed to Delete JOB: "+ group+"-"+name+ "Error is "+e.getMessage();
}
}
public String deleteAllJobs() throws SchedulerException {
sc = getScheduler();
for (String groupName : sc.getJobGroupNames()) {
for (JobKey jobKey : sc.getJobKeys(GroupMatcher.jobGroupEquals(groupName))) {
sc.deleteJob(jobKey);
}
}
return "All Jobs Deleted: ";
}
}
-------------------Service file----------- where i am unable to access the dataSource.
package com.bsq.quartzscheduler.services;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.sql.DataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.JobExecutionContext;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.Trigger.CompletedExecutionInstruction;
import org.quartz.TriggerListener;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.bsq.quartzscheduler.controllers.SimpleCronScheduler;
@Service
public class TriggerListenerService implements TriggerListener {
private final Log logger = LogFactory.getLog(getClass());
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
@Autowired
private SimpleCronScheduler scs;
@Autowired
private DataSource dataSource;
@Override
public String getName() {
return "Main Trigger(IP) Listener";
}
@Override
public void triggerComplete(Trigger trigger, JobExecutionContext context,
CompletedExecutionInstruction triggerInstructionCode) {
// do something with the event
Date date = new Date();
logger.info("Trigger Listerner###: Method: triggerComplete | Time: "+ dateFormat.format(date) +" | Job Name: " + context.getJobDetail().getKey().getName());
}
@Override
public void triggerFired(Trigger trigger, JobExecutionContext context) {
// do something with the event
Date date = new Date();
String sql = "insert into qrtz_logtable (jobName, instance, createTime) values("+context.getJobDetail().getKey().getName()+", "+context.getJobInstance()+","+dateFormat.format(date)+")";
System.out.println("DataSource in tListerner "+dataSource); //Outputs as NULL
try{
scs.insertRecord();
} catch (Exception e) {
System.out.println("ERROR MESSAGE OF SCS: "+e.getMessage()); //Outputs as NULL
}
logger.info("Trigger Listerner###: Method: triggerFired | Time: "+ dateFormat.format(date) +" | Job Name: " + context.getJobDetail().getKey().getName());
}
@Override
public void triggerMisfired(Trigger trigger) {
// do something with the event
String jName;
Date date = new Date();
try {
Scheduler sc = StdSchedulerFactory.getDefaultScheduler();
sc.getContext();
jName = sc.getJobDetail(trigger.getJobKey()).getKey().getName();
logger.info("Trigger Listerner###: Method: triggerMisfired | Time: "+ dateFormat.format(date) +" | Job Name: " + jName);
} catch (SchedulerException e) {
System.out.println("Exception in triggerMisfired " +e.getMessage());
}
System.out.println("Trigger Listener###: Method: triggerMisfired | Time:"+ dateFormat.format(date) +" | Job Name: " + trigger.getKey());
}
@Override
public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {
// do something with the event
boolean veto = false;
Date date = new Date();
logger.info("Trigger Listerner###: Method: vetoJobExecution | Time: "+ dateFormat.format(date) +" | Job Name: " + context.getJobDetail().getKey().getName());
return veto;
}
}