Currently I am trying to get my script to run on a tomcat server by using the basic web container guidelines for spring-batch-boot from the documentation https://docs.spring.io/spring-batch/reference/html/configureJob.html
The script was working correctly as a jar file before modifications to the main class but when I try converting it to a servlet I am having issues with my @PostConstruct
starting only on server startup. This code sets application.properties to spring.batch.job.enabled=false
and has a controller of
@Controller
public class JobLauncherController {
@Autowired
JobLauncher jobLauncher;
@Autowired
Job job;
@RequestMapping("/jobLauncher.html")
public void handle() throws Exception{
jobLauncher.run(job, new JobParameters());
}
With The main Application to start the servlet for tomcat as
@SpringBootApplication
@EnableBatchProcessing
public class BatchApplication extends SpringBootServletInitializer{
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(BatchApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(BatchApplication.class, args);
}
The problem is that my job uses custom item readers and writers that initializes it before running it using @PostConstruct
. It runs the @PostConstruct at server startup which is what helps initialize the beans for writing.
My item readers/writers look like this
public class CustomReader extends ItemStreamSupport implements ItemReader<Acct>, ResourceAwareItemReaderItemStream<Acct> {
//basic autowiring
private int nextAcctIndex;
private List<Acct> acctsList = new ArrayList();
@PostConstruct
private void initialize() throws IOException {
//logic to parse files
acctsList = Collections.unmodifiableList(acctsList);
nextAcctIndex = 0;
}
@Override
public Acct read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
// System.out.println("Start Read");
Acct nextAcct = null;
if (nextAcctIndex < acctsList.size()) {
nextAcct = acctsList.get(nextAcctIndex);
nextAcctIndex++;
//System.out.println(nextAcct);
}
The BatchConfiguration calls everything like most examples as
@Bean public
IteamReader<Acct> CustomReader(){ return new CustomReader();}
My question is am I going about this the wrong way or is there a way to make it so the @PostConstruct
is able to be called only when the Controller request for it?
you need to use
@BeforeStep
public void beforeStep(StepExecution stepExecution) {
init();
}
@PostConstruct
is used to initialize once after applicationContext
is loaded.
In your case you want to run this initialization every time job is running (you don't want data to be leaked across different jobs, right?)