I've been prototyping this all day and I've come up with a solution based on overriding SimpleJob.
By splitting the <batch:job ...../> defintion from the <step....> definitions, I was able to load all jobs (2 at the moment) at startup, but the steps were not loaded until a job instance was actually started.
By subclassing the SimpleJob, I could create it in the spring context as:
Code:
<bean id="jobA" class="ContextLoadingSimpleJob" parent="dailyJobParent" >
<property name="contexts">
<list>
<value>spring/configA.xml</value>
<value>spring/configB.xml</value>
</list>
</property>
</bean>
This is still picked up by the JobRegistrar and so still available for job creation, but does not have the overhead of having all of its objects created thus far.
Then, once a Job Instance is created and the job is run, the doExecute method in Simplejob is overridden in ContextLoadingSimpleJob as:
Code:
@SuppressWarnings("unchecked")
@Override
protected void doExecute(JobExecution execution) throws JobInterruptedException, JobRestartException, StartLimitExceededException {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(contexts.toArray(new String[0]), applicationContext);
setSteps((List<Step>) context.getBean("steps"));
super.doExecute(execution);
context.close();
}
Therefore placing a contract on the spring contexts configured earlier that there must be a List<String> of Step objects to be used by the ContextLoadingSimpleJob.
As I mentioned before, I am only prototyping today so haven't performed any memory analysis on this yet, but once the Job has finished, the context will be closed and everything that isn't being used will hopefully be garbage collected.