<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blog4Java &#187; JSR-352</title>
	<atom:link href="http://malsolo.com/blog4java/?feed=rss2&#038;tag=jsr-352" rel="self" type="application/rss+xml" />
	<link>http://malsolo.com/blog4java</link>
	<description>A personal and Java blog, likely only for me</description>
	<lastBuildDate>Tue, 31 Mar 2015 15:52:42 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=4.1.1</generator>
	<item>
		<title>Introduction to Spring Batch. Part II: more on running a Job</title>
		<link>http://malsolo.com/blog4java/?p=375</link>
		<comments>http://malsolo.com/blog4java/?p=375#comments</comments>
		<pubDate>Thu, 04 Sep 2014 15:45:23 +0000</pubDate>
		<dc:creator><![CDATA[Javier (@jbbarquero)]]></dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Springsource]]></category>
		<category><![CDATA[JSR-352]]></category>
		<category><![CDATA[Spring Batch]]></category>
		<category><![CDATA[Spring Framework]]></category>

		<guid isPermaLink="false">http://malsolo.com/blog4java/?p=375</guid>
		<description><![CDATA[In the previous blog post entry, we introduced Spring Batch with a simple exposition of its features, main concepts both for configuring and running Batch Jobs. We also saw a sample application and two ways of running it: by invoking &#8230; <a href="http://malsolo.com/blog4java/?p=375">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>In the previous blog post entry, <a href="http://malsolo.com/blog4java/?p=260" title="Introduction to Spring Batch" target="_blank">we introduced Spring Batch</a> with a simple exposition of its features, main concepts both for configuring and running Batch Jobs.</p>
<p>We also saw a sample application and two ways of running it: by invoking a <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/JobLauncher.html" title="Interface JobLauncher" target="_blank">JobLauncher</a> bean or by using <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/support/CommandLineJobRunner.html" title="Class CommandLineJobRunner" target="_blank">CommandLineJobRunner</a> from the command line.</p>
<p>In this blog entry, we&#8217;ll see two additional ways to run a Spring Batch job:</p>
<ol>
<li>Using <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/JobOperator.html" title="Interface JobOperator" target="_blank">JobOperator</a>, in order to have control of the batch process, from start a job to monitoring tasks such as stopping, restarting, or summarizing a Job. We&#8217;ll only pay attention to the start operation, but once a <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/JobOperator.html" title="Interface JobOperator" target="_blank">JobOperator</a> is configured, you can use for the remaining monitoring tasks.</li>
<li>Using <a href="http://projects.spring.io/spring-boot/" title="Spring Boot" target="_blank">Spring Boot</a>, the new convention-over-configuration centric framework from the Spring team, that allows you to create with a few lines of code applications that &#8220;just run&#8221;, because Spring Boot provides a lot of features based on what you have in your classpath.</li>
</ol>
<p>As usual, all the source code is available at <a href="https://github.com/jbbarquero/spring-batch-sample" title="My Spring Batch sample at GitHub" target="_blank">GitHub</a>.</p>
<h3>Running the sample: JobOperator</h3>
<p><a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/JobOperator.html" title="Interface JobOperator" target="_blank">JobOperator</a> is an interface that provides operations <a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#JobOperator" title="JobOperator" target="_blank">for inspecting and controlling jobs</a>, mainly for a command-line client or a remote launcher like a JMX console.</p>
<p>The implementation that Spring Batch provides, <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/support/SimpleJobOperator.html" title="Class SimpleJobOperator" target="_blank">SimpleJobOperator</a>, uses <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/JobLauncher.html" title="Interface JobLauncher" target="_blank">JobLauncher</a>, <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/repository/JobRepository.html" title="Interface JobRepository" target="_blank">JobRepository</a>, <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/explore/JobExplorer.html" title="Interface JobExplorer" target="_blank">JobExplorer</a>, and <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/JobRegistry.html" title="Interface JobRegistry" target="_blank">JobRegistry</a> for performing its operations. They are created by the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.html" title="Annotation Type EnableBatchProcessing" target="_blank">@EnableBatchProcessing</a> annotation, so we can create an <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/AdditionalBatchConfiguration.java" title="AdditionalBatchConfiguration.java" target="_blank">additional batch configuration</a> file with these dependencies autowired and later import it in the <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/BatchConfiguration.java" title="BatchConfiguration.java" target="_blank">batch configuration</a> file (not without issues, due to the way Spring loads the application context, we&#8217;ll see this shortly):</p>
<p></p><pre class="crayon-plain-tag">@Configuration
public class AdditionalBatchConfiguration {

    @Autowired
    JobRepository jobRepository;
    @Autowired
    JobRegistry jobRegistry;
    @Autowired
    JobLauncher jobLauncher;
    @Autowired
    JobExplorer jobExplorer;

    @Bean
    public JobOperator jobOperator() {
        SimpleJobOperator jobOperator = new SimpleJobOperator();
        jobOperator.setJobExplorer(jobExplorer);
        jobOperator.setJobLauncher(jobLauncher);
        jobOperator.setJobRegistry(jobRegistry);
        jobOperator.setJobRepository(jobRepository);
        return jobOperator;
    }

}</pre><p></p>
<p>And the <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/context/annotation/Import.html" title="Annotation Type Import" target="_blank">@Import</a>:</p>
<p></p><pre class="crayon-plain-tag">@Configuration
@EnableBatchProcessing
@Import(AdditionalBatchConfiguration.class)
public class BatchConfiguration {

	// Omitted

}</pre><p></p>
<p>Now it seems easy to run the job with a <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/MainJobOperator.java" title="MainJobOperator.java" target="_blank">main class</a>:</p>
<p></p><pre class="crayon-plain-tag">@Component
public class MainJobOperator {

    @Autowired
    JobOperator jobOperator;

    @Autowired
    Job importUserJob;

    public static void main(String... args) throws JobParametersInvalidException, JobInstanceAlreadyExistsException, NoSuchJobException, DuplicateJobException, NoSuchJobExecutionException {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfiguration.class);

        MainJobOperator main = context.getBean(MainJobOperator.class);
        long executionId = main.jobOperator.start(main.importUserJob.getName(), null);

        MainHelper.reportResults(main.jobOperator, executionId);
        MainHelper.reportPeople(context.getBean(JdbcTemplate.class));

        context.close();

        System.out.printf(&quot;\nFIN %s&quot;, main.getClass().getName());

    }
}</pre><p></p>
<p>But there&#8217;s a little problem&#8230; it doesn&#8217;t work:</p>
<p></p><pre class="crayon-plain-tag">Exception in thread "main" org.springframework.batch.core.launch.NoSuchJobException: No job configuration with the name [importUserJob] was registered
	at org.springframework.batch.core.configuration.support.MapJobRegistry.getJob(MapJobRegistry.java:66)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:483)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
	at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
	at com.sun.proxy.$Proxy14.getJob(Unknown Source)
	at org.springframework.batch.core.launch.support.SimpleJobOperator.start(SimpleJobOperator.java:310)
	at com.malsolo.springframework.batch.sample.MainJobOperator.main(MainJobOperator.java:15)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:483)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

Process finished with exit code 1</pre><p></p>
<p>The problem here, <em><font color=red>No job configuration with the name [<strong>importUserJob</strong>] was registered</font></em>, is due to the way that <a href="http://docs.spring.io/spring-batch/apidocs/org/springframework/batch/core/launch/JobOperator.html#start-java.lang.String-java.lang.String-" title="API" target="_blank">JobOperator.start(String jobName, String parameters)</a> works.</p>
<p>The main difference with <a href="http://docs.spring.io/spring-batch/apidocs/org/springframework/batch/core/launch/JobLauncher.html#run-org.springframework.batch.core.Job-org.springframework.batch.core.JobParameters-" title="API" target="_blank">JobLauncher.run(Job job, JobParameters jobParameters)</a> is that the former has String as parameters while the latter uses objects directly.</p>
<p>So <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/JobOperator.html" title="Interface JobOperator" target="_blank">JobOperator</a>, actually <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/support/SimpleJobOperator.html" title="Class SimpleJobOperator" target="_blank">SimpleJobOperator</a>, has to obtain a <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/Job.html" title="Interface Job" target="_blank">Job</a> with the provided name. In order to do so, it uses the <a href="http://docs.spring.io/spring-batch/apidocs/org/springframework/batch/core/configuration/JobLocator.html#getJob-java.lang.String-" title="API" target="_blank">JobRegistry.getJob(String name)</a> method. The available Spring Batch implementation is <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/support/MapJobRegistry.html" title="Class MapJobRegistry" target="_blank">MapJobRegistry</a> that uses a ConcurrentMap to store using the job name as the key, a <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/JobFactory.html" title="Interface JobFactory" target="_blank">JobFactory</a> to create the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/Job.html" title="Interface Job" target="_blank">Job</a> when requested.</p>
<p>The problem is that this map has not been populated.</p>
<p>The first solution is easy: the JobRegistry allows you to register at runtime a JobFactory to later obtain the Job as explained above. So, we only need to create this JobFactory&#8230;</p>
<p></p><pre class="crayon-plain-tag">@Configuration
public class AdditionalBatchConfiguration {
//    Rest omitted
    @Autowired
    Job importUserJob;

    @Bean
    public JobFactory jobFactory() {
        return new ReferenceJobFactory(importUserJob);
    }
}</pre><p></p>
<p>&#8230;and register it in the main method:</p>
<p></p><pre class="crayon-plain-tag">@Component
public class MainJobOperator {

    @Autowired
    JobFactory jobFactory;
    @Autowired
    JobRegistry jobRegistry;
    @Autowired
    JobOperator jobOperator;

    @Autowired
    Job importUserJob;

    public static void main(String... args) throws JobParametersInvalidException, JobInstanceAlreadyExistsException, NoSuchJobException, DuplicateJobException, NoSuchJobExecutionException {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfiguration.class);

        MainJobOperator main = context.getBean(MainJobOperator.class);
        main.jobRegistry.register(main.jobFactory);
        long executionId = main.jobOperator.start(main.importUserJob.getName(), null);

        MainHelper.reportResults(main.jobOperator, executionId);
        MainHelper.reportPeople(context.getBean(JdbcTemplate.class));

        context.close();

        System.out.printf(&quot;\nFIN %s&quot;, main.getClass().getName());

    }
}</pre><p></p>
<p>And now it works:</p>
<p></p><pre class="crayon-plain-tag">***********************************************************
JobExecution: id=0, version=2, startTime=2014-09-04 13:03:37.964, endTime=2014-09-04 13:03:38.141, lastUpdated=2014-09-04 13:03:38.141, status=COMPLETED, exitStatus=exitCode=COMPLETED;exitDescription=, job=[JobInstance: id=0, version=0, Job=[importUserJob]], jobParameters=[{}]
* Steps executed:
StepExecution: id=0, version=3, name=step1, status=COMPLETED, exitStatus=COMPLETED, readCount=5, filterCount=0, writeCount=5 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
***********************************************************
***********************************************************
* People found:

* Found firstName: JILL, lastName: DOE in the database

* Found firstName: JOE, lastName: DOE in the database

* Found firstName: JUSTIN, lastName: DOE in the database

* Found firstName: JANE, lastName: DOE in the database

* Found firstName: JOHN, lastName: DOE in the database
***********************************************************</pre><p></p>
<p>But I don&#8217;t like this approach, it&#8217;s too manual.</p>
<p>I&#8217;d rather to populate the JobRegistry automatically, and Spring Batch provides two mechanisms for doing so, <a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#d4e1228" title="JobRegistryBeanPostProcessor" target="_blank">a bean post-processor</a>, <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/support/JobRegistryBeanPostProcessor.html" title="Class JobRegistryBeanPostProcessor" target="_blank">JobRegistryBeanPostProcessor</a>, and <a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#d4e1233" title="AutomaticJobRegistrar" target="_blank"> a component</a> that loads and unloads Jobs by creating child context and registering  jobs from those contexts as they are created, <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/support/AutomaticJobRegistrar.html" title="Class AutomaticJobRegistrar" target="_blank">AutomaticJobRegistrar</a>.</p>
<p>We&#8217;ll see the post-processor approach, because it&#8217;s very easy. Just declare the bean in the Batch configuration and run the original main class.</p>
<p></p><pre class="crayon-plain-tag">@Configuration
@EnableBatchProcessing
@Import(AdditionalBatchConfiguration.class)
public class BatchConfiguration {

	// Omitted

    @Bean
    public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor(JobRegistry jobRegistry) {
        JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor = new JobRegistryBeanPostProcessor();
        jobRegistryBeanPostProcessor.setJobRegistry(jobRegistry);
        return jobRegistryBeanPostProcessor;
    }

}</pre><p></p>
<p>The bean post processor has to be declared in this configuration file for registering the job when it&#8217;s created (this is the issue that I mentioned before, if you declare the post processor in another java file configuration, for instance in the <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/AdditionalBatchConfiguration.java" title="AdditionalBatchConfiguration.java" target="_blank">AdditionalBatchConfiguration</a> it will never receive the job bean). It uses the same <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/JobRegistry.html" title="Interface JobRegistry" target="_blank">JobRegistry</a> that uses the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/JobOperator.html" title="Interface JobOperator" target="_blank">JobOperator</a> to launch the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/Job.html" title="Interface Job" target="_blank">Job</a>. Actually the only that exists, but it&#8217;s good to know this.</p>
<p>It also works:</p>
<p></p><pre class="crayon-plain-tag">***********************************************************
JobExecution: id=0, version=2, startTime=2014-09-04 13:20:07.343, endTime=2014-09-04 13:20:07.522, lastUpdated=2014-09-04 13:20:07.522, status=COMPLETED, exitStatus=exitCode=COMPLETED;exitDescription=, job=[JobInstance: id=0, version=0, Job=[importUserJob]], jobParameters=[{}]
* Steps executed:
StepExecution: id=0, version=3, name=step1, status=COMPLETED, exitStatus=COMPLETED, readCount=5, filterCount=0, writeCount=5 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
***********************************************************
***********************************************************
* People found:

* Found firstName: JILL, lastName: DOE in the database

* Found firstName: JOE, lastName: DOE in the database

* Found firstName: JUSTIN, lastName: DOE in the database

* Found firstName: JANE, lastName: DOE in the database

* Found firstName: JOHN, lastName: DOE in the database
***********************************************************</pre><p></p>
<h3>Running the sample: Spring Boot</h3>
<p>We&#8217;d like to try how quickly and easy is Spring Boot for launching Spring Batch applications once we already have a functional configuration.</p>
<p>And it seems to be a piece of cake (the problem here is to know what is happening under the hood)</p>
<p></p><pre class="crayon-plain-tag">package com.malsolo.springframework.batch.sample;
@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = ApplicationConfiguration.class)})
@EnableAutoConfiguration
public class MainBoot {

    public static void main(String... args) {

        ApplicationContext context = SpringApplication.run(MainBoot.class);

        MainHelper.reportPeople(context.getBean(JdbcTemplate.class));

    }
}</pre><p></p>
<p>Actually, Spring Boot is out of the bounds of this topic, it deserves its own entry (even, an entire book) but we can summarize the important code here:</p>
<ul>
<li>Line 3: <a href="http://docs.spring.io/spring-boot/docs/current/api/index.html?org/springframework/boot/autoconfigure/EnableAutoConfiguration.html" title="Annotation Type EnableAutoConfiguration" target="_blank">@EnableAutoConfiguration</a>, with this annotation you want Spring Boot to instantiate the beans that you&#8217;re going to need based on the libraries on your classpath.</li>
<li>Line 8: <a href="http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/SpringApplication.html#run(java.lang.Object[], java.lang.String[])" title="API" target="_blank">the run method</a>, to bootstrap the application by passing the class itself (in our case, <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/MainBoot.java" title="MainBoot.java" target="_blank">MainBoot</a>) that serves as the primary Spring component.
</ul>
<p>It&#8217;s enough to run the Batch application:</p>
<p></p><pre class="crayon-plain-tag">.   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.1.4.RELEASE)

2014-09-04 16:58:55.109  INFO 15646 --- [           main] c.m.s.batch.sample.MainBoot              : Starting MainBoot on jbeneito-Latitude-3540 with PID 15646 (/home/jbeneito/Documents/git/spring-batch-sample/target/classes started by jbeneito in /home/jbeneito/Documents/git/spring-batch-sample)
2014-09-04 16:58:55.237  INFO 15646 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@6366ebe0: startup date [Thu Sep 04 16:58:55 CEST 2014]; root of context hierarchy
2014-09-04 16:58:56.039  INFO 15646 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'jdbcTemplate': replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=batchConfiguration; factoryMethodName=jdbcTemplate; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/malsolo/springframework/batch/sample/BatchConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=mainForSpringInfo; factoryMethodName=jdbcTemplate; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/malsolo/springframework/batch/sample/MainForSpringInfo.class]]
2014-09-04 16:58:56.691  WARN 15646 --- [           main] o.s.c.a.ConfigurationClassEnhancer       : @Bean method ScopeConfiguration.stepScope is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean Javadoc for complete details
2014-09-04 16:58:56.724  WARN 15646 --- [           main] o.s.c.a.ConfigurationClassEnhancer       : @Bean method ScopeConfiguration.jobScope is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean Javadoc for complete details
2014-09-04 16:58:56.729  INFO 15646 --- [           main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
2014-09-04 16:58:56.975  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'batchConfiguration' of type [class com.malsolo.springframework.batch.sample.BatchConfiguration$$EnhancerBySpringCGLIB$$c3ec56ab] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:57.145  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [class org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$5a15b25b] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:57.238  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'transactionAttributeSource' of type [class org.springframework.transaction.annotation.AnnotationTransactionAttributeSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:57.294  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'transactionInterceptor' of type [class org.springframework.transaction.interceptor.TransactionInterceptor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:57.301  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.config.internalTransactionAdvisor' of type [class org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:57.374  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'dataSourceConfiguration' of type [class com.malsolo.springframework.batch.sample.DataSourceConfiguration$$EnhancerBySpringCGLIB$$18a97d02] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:57.455  INFO 15646 --- [           main] o.s.j.d.e.EmbeddedDatabaseFactory        : Creating embedded database 'testdb'
2014-09-04 16:58:58.156  INFO 15646 --- [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executing SQL script from class path resource [schema-all.sql]
2014-09-04 16:58:58.178  INFO 15646 --- [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executed SQL script from class path resource [schema-all.sql] in 20 ms.
2014-09-04 16:58:58.178  INFO 15646 --- [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executing SQL script from class path resource [org/springframework/batch/core/schema-hsqldb.sql]
2014-09-04 16:58:58.189  INFO 15646 --- [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executed SQL script from class path resource [org/springframework/batch/core/schema-hsqldb.sql] in 11 ms.
2014-09-04 16:58:58.198  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'dataSource' of type [class org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory$EmbeddedDataSourceProxy] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:58.206  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$DataSourceInitializerConfiguration' of type [class org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration$DataSourceInitializerConfiguration$$EnhancerBySpringCGLIB$$c0608242] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:58.257  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'spring.datasource.CONFIGURATION_PROPERTIES' of type [class org.springframework.boot.autoconfigure.jdbc.DataSourceProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:58.260  INFO 15646 --- [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executing SQL script from URL [file:/home/jbeneito/Documents/git/spring-batch-sample/target/classes/schema-all.sql]
2014-09-04 16:58:58.262  INFO 15646 --- [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executed SQL script from URL [file:/home/jbeneito/Documents/git/spring-batch-sample/target/classes/schema-all.sql] in 2 ms.
2014-09-04 16:58:58.263  WARN 15646 --- [           main] o.s.b.a.jdbc.DataSourceInitializer       : Could not send event to complete DataSource initialization (ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.context.annotation.AnnotationConfigApplicationContext@6366ebe0: startup date [Thu Sep 04 16:58:55 CEST 2014]; root of context hierarchy)
2014-09-04 16:58:58.263  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'dataSourceInitializer' of type [class org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:58.277  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration' of type [class org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$$EnhancerBySpringCGLIB$$85a27e41] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:58.320  INFO 15646 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'jobRegistry' of type [class com.sun.proxy.$Proxy25] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-09-04 16:58:58.795  INFO 15646 --- [           main] o.s.b.c.r.s.JobRepositoryFactoryBean     : No database type set, using meta data indicating: HSQL
2014-09-04 16:58:59.056  INFO 15646 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : No TaskExecutor has been set, defaulting to synchronous executor.
2014-09-04 16:58:59.361  INFO 15646 --- [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executing SQL script from class path resource [org/springframework/batch/core/schema-hsqldb.sql]
2014-09-04 16:58:59.381  INFO 15646 --- [           main] o.s.jdbc.datasource.init.ScriptUtils     : Executed SQL script from class path resource [org/springframework/batch/core/schema-hsqldb.sql] in 20 ms.
2014-09-04 16:58:59.890  INFO 15646 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2014-09-04 16:58:59.926  INFO 15646 --- [           main] o.s.b.a.b.JobLauncherCommandLineRunner   : Running default command line with: []
2014-09-04 16:59:00.023  INFO 15646 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [FlowJob: [name=importUserJob]] launched with the following parameters: [{run.id=1}]
2014-09-04 16:59:00.060  INFO 15646 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [step1]
Converting (firstName: Jill, lastName: Doe) into (firstName: JILL, lastName: DOE)
Converting (firstName: Joe, lastName: Doe) into (firstName: JOE, lastName: DOE)
Converting (firstName: Justin, lastName: Doe) into (firstName: JUSTIN, lastName: DOE)
Converting (firstName: Jane, lastName: Doe) into (firstName: JANE, lastName: DOE)
Converting (firstName: John, lastName: Doe) into (firstName: JOHN, lastName: DOE)
2014-09-04 16:59:00.162  INFO 15646 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [FlowJob: [name=importUserJob]] completed with the following parameters: [{run.id=1}] and the following status: [COMPLETED]
2014-09-04 16:59:00.164  INFO 15646 --- [           main] c.m.s.batch.sample.MainBoot              : Started MainBoot in 5.963 seconds (JVM running for 8.019)
***********************************************************
* People found:

* Found firstName: JILL, lastName: DOE in the database

* Found firstName: JOE, lastName: DOE in the database

* Found firstName: JUSTIN, lastName: DOE in the database

* Found firstName: JANE, lastName: DOE in the database

* Found firstName: JOHN, lastName: DOE in the database
***********************************************************
2014-09-04 16:59:00.258  INFO 15646 --- [       Thread-1] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@6366ebe0: startup date [Thu Sep 04 16:58:55 CEST 2014]; root of context hierarchy
2014-09-04 16:59:00.262  INFO 15646 --- [       Thread-1] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown

Process finished with exit code 0</pre><p></p>
<p>As a side note, this class already scans for compontents, so we don’t need to make an additional scan for components, so we exclude the <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/ApplicationConfiguration.java" title="ApplicationConfiguration.java" target="_blank">ApplicationConfiguration</a> class with a filter.</p>
<p>Finally, we use the <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/MainHelper.java" title="MainHelper.java" target="_blank">MainHelper</a> class to show a summary of the results.</p>
<p>That&#8217;s all for now, because one more time this entry is growing really fast. Thus, we&#8217;ll see in the next post the last topic of Spring Batch that I want to talk about: <a href="https://jcp.org/en/jsr/detail?id=352" title="JSR 352: Batch Applications for the Java Platform" target="_blank">JSR 352</a>.</p>
<h3>Resources</h3>
<ul>
<li><a href="https://www.youtube.com/watch?v=lHCPppMlylY" title="Youtube" target="_blank">Webinar: Spring Batch 3.0.0</a> by <strong>Michael Minella</strong>. Published on Jun 18, 2014.</li>
<li><a href="https://www.youtube.com/watch?v=yKs4yPs-5yU" title="youtube" target="_blank">JSR-352, Spring Batch and You</a> by <strong>Michael Minella</strong>. Published on Feb 3, 2014.</li>
<li><a href="https://www.youtube.com/watch?v=8tiqeV07XlI" title="youtube" target="_blank">Integrating Spring Batch and Spring Integration</a> by <strong>Gunnar Hillert</strong>, <strong>Michael Minella</strong>. Published on Jul 9, 2014.</li>
<li><a href="http://www.amazon.com/Pro-Spring-Batch-Experts-Voice/dp/1430234520/ref=sr_1_1?ie=UTF8&#038;qid=1409752293&#038;sr=8-1&#038;keywords=pro+spring+batch" title="Amazon" target="_blank">Pro Spring Batch (Expert&#8217;s Voice in Spring)</a> by <strong>Michael Minella</strong>. Published on July 12, 2011 by <a href="http://www.apress.com/9781430234524" title="Apress" target="_blank">Apress</a>.</li>
<li>Spring Batch in Action by <strong>Arnaud Cogoluegnes</strong>, <strong>Thierry Templier</strong>, <strong>Gary Gregory</strong>, <strong>Olivier Bazoud</strong>. Published on October 10, 2011 by <a href="http://www.manning.com/templier/" title="Manning" target="_blank">Manning Publications</a>.</li>
<li>Spring.io GETTING STARTED GUIDE: <a href="http://spring.io/guides/gs/batch-processing/" title="GETTING STARTED: Creating a Batch Service" target="_blank">Creating a Batch Service</a>.
<li><a href="http://docs.spring.io/spring-batch/trunk/reference/html/" title="Spring Batch - Reference Documentation" target="_blank">Spring Batch &#8211; Reference Documentation</a></li>
<li><a href="http://docs.spring.io/spring-batch/apidocs/index.html?overview-summary.html" title="Spring Batch 3.0.1.RELEASE API" target="_blank">Spring Batch &#8211; API specification</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://malsolo.com/blog4java/?feed=rss2&#038;p=375</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introduction to Spring Batch</title>
		<link>http://malsolo.com/blog4java/?p=260</link>
		<comments>http://malsolo.com/blog4java/?p=260#comments</comments>
		<pubDate>Wed, 03 Sep 2014 10:58:02 +0000</pubDate>
		<dc:creator><![CDATA[Javier (@jbbarquero)]]></dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Springsource]]></category>
		<category><![CDATA[JSR-352]]></category>
		<category><![CDATA[Spring Batch]]></category>
		<category><![CDATA[Spring Framework]]></category>

		<guid isPermaLink="false">http://malsolo.com/blog4java/?p=260</guid>
		<description><![CDATA[Spring Batch is the Spring Project aimed to write Java Batch applications by using the foundations of Spring Framework. Michael T. Minella, project lead of Spring Batch and also a member of the JSR 352 (Batch Applications for the Java &#8230; <a href="http://malsolo.com/blog4java/?p=260">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p><a href="http://projects.spring.io/spring-batch/" title="Spring Batch" target="_blank">Spring Batch</a> is the <a href="http://spring.io/projects" title="Spring Projects" target="_blank">Spring Project</a> aimed <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/DefaultBatchConfigurer.html" title="Class DefaultBatchConfigurer" target="_blank"></a>to write Java Batch applications by using the foundations of Spring Framework.</p>
<p><a href="http://spring.io/team/mminella" title="Michael Minella" target="_blank">Michael T. Minella</a>, project lead of Spring Batch and also a member of the <a href="https://jcp.org/en/jsr/detail?id=352" title="JSR 352" target="_blank">JSR 352 (Batch Applications for the Java Platform)</a> expert group, wrote in his book <a href="http://www.amazon.com/Pro-Spring-Batch-Experts-Voice/dp/1430234520" title="Pro Spring Batch" target="_blank">Pro Spring Batch</a> the next definition &#8220;<em>Batch processing [&#8230;] is defined as the processing of data without interaction or interruption. Once started, a batch process runs to some form of completion without any intervention</em>&#8220;.</p>
<p>Typically Batch Jobs are long-running, non-interactive and process large volumes of data, more than fits in memory or a single transaction. Thus they usually run outside office hours and include logic for handling errors   and restarting if necessary.</p>
<p>Spring Batch provides, among others, the next features:</p>
<ul>
<li>Transaction management, to allow you to focus on business processing.</li>
<li>Chunk based processing, to process a large value of data by dividing it in small pieces.</li>
<liDeclarative I/O, by providing readers and writers for a lot of scenarios.</li>
<li>Start/Stop/Restart/Skip/Retry capabilities, to handle non-interactive management of the process.</li>
<li>Web based administration interface (Spring Batch Admin), it provides an API for administering tasks.</li>
<li>Based on Spring framework, so it includes all the configuration options, including Dependency Injection.</li>
<li>Compliance with JSR 352: Batch Applications for the Java Platform.</li>
</ul>
<h3>Spring Batch concepts</h3>
<div id="attachment_266" style="width: 310px" class="wp-caption alignnone"><a href="http://malsolo.com/blog4java/wp-content/uploads/2014/08/spring-batch-reference-model.png"><img src="http://malsolo.com/blog4java/wp-content/uploads/2014/08/spring-batch-reference-model-300x119.png" alt="The Domain Language of Batch" width="300" height="119" class="size-medium wp-image-266" /></a><p class="wp-caption-text">Batch Stereotypes</p></div>
<ul>
<li><a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#domainJob" title="Job" target="_blank">Job</a>: an entity that encapsulates an entire batch process. It is composed of one or more ordered <strong>Steps</strong> and it has some properties such as restartability.</li>
<li><a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#domainStep" title="Step" target="_blank">Step</a>: a domain object that encapsulates an independent, sequential phase of a batch job.</li>
<li><a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#readersAndWriters" title="ItemReaders and ItemWriters and  ItemProcessors" target="_blank">Item</a>: the individual piece of data that it&#8217;s been processed.</li>
<li><a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#chunkOrientedProcessing" title="Chunk-Oriented Processing" target="_blank">Chunk</a>: the processing style used by Spring Batch: read and process the item and then aggregate until reach a number of items, called &#8220;<em>chunk</em>&#8221; that will be finally written.</li>
<div id="attachment_271" style="width: 310px" class="wp-caption alignnone"><a href="http://malsolo.com/blog4java/wp-content/uploads/2014/08/chunk-oriented-processing.png"><img src="http://malsolo.com/blog4java/wp-content/uploads/2014/08/chunk-oriented-processing-300x165.png" alt="Chunk-Oriented Processing" width="300" height="165" class="size-medium wp-image-271" /></a><p class="wp-caption-text">Chunk-Oriented Processing</p></div>
<li><a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#domainJobLauncher" title="JobLauncher" target="_blank">JobLauncher</a>: the entry point to launch Spring Batch jobs with a given set of JobParameters.</li>
<li><a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#domainJobRepository" title="JobRepository" target="_blank">JobRepository</a>: maintains all metadata related to job executions and provides CRUD operations for JobLauncher, Job, and Step implementations.</li>
</ul>
<h3>Running a Job</h3>
<p>The <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/JobLauncher.html" title="JobLauncher API" target="_blank">JobLauncher</a> interface has a basic implementation <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/support/SimpleJobLauncher.html" title="SimpleJobLauncher API" target="_blank">SimpleJobLauncher</a> whose only required dependency is a <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/repository/JobRepository.html" title="JobRepository API" target="_blank">JobRepository</a>, in order to obtain an execution, so that you can use it for executing the Job.</p>
<div id="attachment_275" style="width: 310px" class="wp-caption alignnone"><a href="http://malsolo.com/blog4java/wp-content/uploads/2014/08/job-launcher-sequence-sync.png"><img src="http://malsolo.com/blog4java/wp-content/uploads/2014/08/job-launcher-sequence-sync-300x229.png" alt="JobLauncher" width="300" height="229" class="size-medium wp-image-275" /></a><p class="wp-caption-text">JobLauncher</p></div>
<p>You can also launch a Job asynchronously by configuring a <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/core/task/TaskExecutor.html" title="TaskExecutor API" target="_blank">TaskExecutor</a>. You can also this configuration <a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#runningJobsFromWebContainer" title="Running Jobs from within a Web Container" target="_blank">for running Jobs from within a Web Container</a>.</p>
<div id="attachment_277" style="width: 310px" class="wp-caption alignnone"><a href="http://malsolo.com/blog4java/wp-content/uploads/2014/08/job-launcher-sequence-async.png"><img src="http://malsolo.com/blog4java/wp-content/uploads/2014/08/job-launcher-sequence-async-300x229.png" alt="Job launcher sequence async" width="300" height="229" class="size-medium wp-image-277" /></a><p class="wp-caption-text">Job launcher sequence async</p></div>
<p>A <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/JobLauncher.html" title="JobLauncher API" target="_blank">JobLauncher</a> uses the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/repository/JobRepository.html" title="JobRepository API" target="_blank">JobRepository</a> to create new <strong>JobExecution</strong> objects and run them.</p>
<div id="attachment_281" style="width: 310px" class="wp-caption alignnone"><a href="http://malsolo.com/blog4java/wp-content/uploads/2014/08/job-repository.png"><img src="http://malsolo.com/blog4java/wp-content/uploads/2014/08/job-repository-300x265.png" alt="Job Repository" width="300" height="265" class="size-medium wp-image-281" /></a><p class="wp-caption-text">Job Repository</p></div>
<h3>Running Jobs: concepts</h3>
<p>The main concepts related with Job execution are</p>
<div id="attachment_283" style="width: 310px" class="wp-caption alignnone"><a href="http://malsolo.com/blog4java/wp-content/uploads/2014/08/jobHeirarchyWithSteps.png"><img src="http://malsolo.com/blog4java/wp-content/uploads/2014/08/jobHeirarchyWithSteps-300x220.png" alt="Job hierarchy with steps" width="300" height="220" class="size-medium wp-image-283" /></a><p class="wp-caption-text">Job hierarchy with steps</p></div>
<ul>
<li><a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/JobInstance.html" title="JobInstance API" target="_blank">JobInstance</a>: a logical run of a Job.</li>
<li><a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/JobParameter.html" title="JobParameter API" target="_blank">JobParameters</a>: a set of parameters used to start a batch job. It categorizes each JobInstance.</li>
<li><a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/JobExecution.html" title="JobExecution API" target="_blank">JobExecution</a>: physical runs of Jobs, in order to know what happens with the execution.</li>
<li><a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/StepExecution.html" title="StepExecution API" target="_blank">StepExecution</a>: a single attempt to execute a Step, that is created each time a Step is run and it also provides information regarding the result of the processing.</li>
<li><a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/item/ExecutionContext.html" title="ExecutionContext API" target="_blank">ExecutionContext</a>: a collection of key/value pairs that are persisted and controlled by the framework in order to allow developers a place to store persistent state that is scoped to a StepExecution or JobExecution.</li>
</ul>
<h3>Sample application</h3>
<p>Now we are going to see a simple sample application that reads a POJO that represents a Person from a file containing People data and after processing each  of them, that is just uppercase its attributes, saving them in a database.</p>
<p>All the code is available at <a href="https://github.com/jbbarquero/spring-batch-sample" title="My Spring Batch sample at GitHub" target="_blank">GitHub</a>. </p>
<p>Let&#8217;s begin with the basic domain class: <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/Person.java" title="Person.java" target="_blank">Person</a>, just a POJO.</p>
<p></p><pre class="crayon-plain-tag">package com.malsolo.springframework.batch.sample;

public class Person {
    private String lastName;
    private String firstName;
    //...
}</pre><p></p>
<p>Then, let&#8217;s see the simple processor, <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/PersonItemProcessor.java" title="PersonItemProcessor.java" target="_blank">PersonItemProcessor</a>. It implements an <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/item/ItemProcessor.html" title="ItemProcessor API" target="_blank">ItemProcessor</a>, with a Person both as Input and Output.</p>
<p>It provides a method to be overwritten, <strong>process</strong>, that allows you to write the custom transformation.</p>
<p></p><pre class="crayon-plain-tag">package com.malsolo.springframework.batch.sample;

import org.springframework.batch.item.ItemProcessor;

public class PersonItemProcessor implements ItemProcessor&lt;Person, Person&gt; {

    @Override
    public Person process(final Person person) throws Exception {
        final String firstName = person.getFirstName().toUpperCase();
        final String lastName = person.getLastName().toUpperCase();

        final Person transformedPerson = new Person(firstName, lastName);

        System.out.println(&quot;Converting (&quot; + person + &quot;) into (&quot; + transformedPerson + &quot;)&quot;);

        return transformedPerson;
    }

}</pre><p></p>
<p>Once done this, we can proceed to configure the Spring Batch Application, for doing so, we&#8217;ll use Java Annotations in a <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/BatchConfiguration.java" title="BatchConfiguration.java" target="_blank">BatchConfiguration</a> file:</p>
<p></p><pre class="crayon-plain-tag">// Imports and package omitted
@Configuration
@EnableBatchProcessing
@Import(AdditionalBatchConfiguration.class)
public class BatchConfiguration {

	// Input, processor, and output definition
	
	@Bean
    public ItemReader&lt;Person&gt; reader() {
		FlatFileItemReader&lt;Person&gt; reader = new FlatFileItemReader&lt;Person&gt;();
		reader.setResource(new ClassPathResource(&quot;sample-data.csv&quot;));
		reader.setLineMapper(new DefaultLineMapper&lt;Person&gt;() {{
			setLineTokenizer(new DelimitedLineTokenizer() {{
				setNames(new String[] {&quot;firstName&quot;, &quot;lastName&quot;});
			}});
			setFieldSetMapper(new BeanWrapperFieldSetMapper&lt;Person&gt;() {{
				setTargetType(Person.class);
			}});
			
		}});
		return reader;
	}
	
	@Bean
    public ItemProcessor&lt;Person, Person&gt; processor() {
        return new PersonItemProcessor();
    }
	
	@Bean
    public ItemWriter&lt;Person&gt; writer(DataSource dataSource) {
		JdbcBatchItemWriter&lt;Person&gt; writer = new JdbcBatchItemWriter&lt;Person&gt;();
		writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider&lt;Person&gt;());
		writer.setSql(&quot;INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)&quot;);
		writer.setDataSource(dataSource);
		return writer;
	}
	
	//  Actual job configuration
	
	@Bean
    public Job importUserJob(JobBuilderFactory jobs, Step s1) {
		return jobs.get(&quot;importUserJob&quot;)
				.incrementer(new RunIdIncrementer())
				.flow(s1)
				.end()
				.build();
	}
	
	@Bean
    public Step step1(StepBuilderFactory stepBuilderFactory, ItemReader&lt;Person&gt; reader,
            ItemWriter&lt;Person&gt; writer, ItemProcessor&lt;Person, Person&gt; processor) {
		return stepBuilderFactory.get(&quot;step1&quot;)
				.&lt;Person, Person&gt; chunk(10)
				.reader(reader)
				.processor(processor)
				.writer(writer)
				.build();
	}
	
	@Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
	
}</pre><p></p>
<p>Highlights for this class are:</p>
<ul>
<li>Line 2: <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/context/annotation/Configuration.html" title="Configuration API" target="_blank">@Configuration</a>, this class will be processed by the <a href="http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-java-basic-concepts" title="Java-based container configuration, basic concepts." target="_blank">Spring container to generate bean definitions</a>.</li>
<li>Line 3: <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.html" title="EnableBatchProcessing API" target="_blank">@EnableBatchProcessing</a>, provides a base configuration for building batch jobs <a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#javaConfig" title="Spring Batch Java Config" target="_blank">by creating the next beans beans available to be autowired</a>:
<ul>
<li>JobRepository &#8211; bean name &#8220;jobRepository&#8221;</li>
<li>JobLauncher &#8211; bean name &#8220;jobLauncher&#8221;</li>
<li>JobRegistry &#8211; bean name &#8220;jobRegistry&#8221;</li>
<li>PlatformTransactionManager &#8211; bean name &#8220;transactionManager&#8221;</li>
<li>JobBuilderFactory &#8211; bean name &#8220;jobBuilders&#8221;</li>
<li>StepBuilderFactory &#8211; bean name &#8220;stepBuilders&#8221;</li>
</ul>
<p>We&#8217;ll see shortly how it works.</li>
<li>Line 10: the <strong>reader bean</strong>, an instance of a <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/item/file/FlatFileItemReader.html" title="Class FlatFileItemReader&lt;T&gt;" target="_blank">FlatFileItemReader</a>, that implements the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/item/ItemReader.html" title="Interface ItemReader&lt;T&gt;" target="_blank">ItemReader</a> interface to read each <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/Person.java" title="Person.java" target="_blank">Person</a> from the file containing people. Spring Batch provides several implementations for this interface, being this implementation that read lines from one Resource one of them.You know, <u>no need of custom code</u>.</li>
<li>Line 26: the <strong>processor bean</strong>, an instance of the previously defined <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/PersonItemProcessor.java" title="PersonItemProcessor.java" target="_blank">PersonItemProcessor</a>. See above.</li>
<li>Line 31: the <strong>writer bean</strong>, an instance of a <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/item/database/JdbcBatchItemWriter.html" title="Class JdbcBatchItemWriter&lt;T&gt;" target="_blank">JdbcBatchItemWriter</a>, that implements the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/item/ItemWriter.html" title="Interface ItemWriter&lt;T&gt;" target="_blank">ItemWriter interface</a> to write the People already processed to the database. It&#8217;s also an implementation provided by Spring Batch, so <u>no need of custom code</u> again. In this case, you only have to provide an SQL, and a callback for the parameters. Since we are using named parameters, we&#8217;ve chosen a <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/item/database/BeanPropertyItemSqlParameterSourceProvider.html" title="Class BeanPropertyItemSqlParameterSourceProvider&lt;T&gt;" target="_blank">BeanPropertyItemSqlParameterSourceProvider</a>. This bean also needs a DataSource, so we provided it by passing one as a method parameter in order to Spring inject the instance that it has registered.</li>
<li>Line 42: a <strong><a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/Job.html" title="Interface Job" target="_blank">Job</a> bean</strong>, that it&#8217;s built using the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/JobBuilderFactory.html" title="Class JobBuilderFactory" target="_blank">JobBuilderFactory</a> that is autowired by passing it as method parameter for this @Bean method. When you call its get method, Spring Batch will create a <strong>job builder</strong> and will initialize its job repository, the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/job/builder/JobBuilder.html" title="Class JobBuilder" target="_blank">JobBuilder</a> is the convenience class for building jobs of various kinds as you can see in the code above. We also use a <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/Step.html" title="Interface Step" target="_blank">Step</a> that is configured as the next Spring bean.</li>
<li>Line 51: a <strong><a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/Step.html" title="Interface Step" target="_blank">Step</a> bean</strong>, that it’s built using the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/StepBuilderFactory.html" title="Class StepBuilderFactory" target="_blank">StepBuilderFactory</a> that is autowired by passing it as method parameter for this @Bean method, as well as the other dependencies: the <strong>reader</strong>, the <strong>processor</strong> and the <strong>writer</strong> previously defined. When calling the get method from the StepBuilderFactory, Spring Batch will create a step builder and will initialize its job repository and transaction manager, the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/step/builder/StepBuilder.html" title="Class StepBuilder" target="_blank">StepBuilder</a> is an entry point for building all kinds of steps as you can see in the code above.
</ul>
<p>This configuration is almost everything needed to configure a Batch process as defined in the concepts above.</p>
<p>Actually, only one configuration class needs to have the @EnableBatchProcessing annotation in order to have the base configuration for building batch jobs. Then you can define the job with their steps and the readers/processors/writers that they need.</p>
<p>But an additional data source is needed to be used by the <strong>JobRepository</strong>. For this sample we&#8217;ll use an in-memory one:</p>
<p></p><pre class="crayon-plain-tag">@Configuration
public class DataSourceConfiguration {

    @Bean
    public DataSource dataSource() {
        EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
        return builder
                .setType(HSQL)
                .addScript(&quot;schema-all.sql&quot;)
                .addScript(&quot;org/springframework/batch/core/schema-hsqldb.sql&quot;)
                .build();
    }

}</pre><p></p>
<p>In this case we&#8217;ll use the same in-memory database, HSQL, with the schema for the application (line 9) and the schema for the job repository (line 10). The former is available as a resource of the application, the file called <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/resources/schema-all.sql" title="src/main/resources/schema-all.sql" target="_blank">schema-all.sql</a>, and the latter in the spring-batch-core jar (spring-batch-core-3.0.1.RELEASE.jar at the time of this writing)</p>
<h3>Alternate Configuration</h3>
<p>The official documentation shows an slightly different <a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#javaConfig" title="Java Config" target="_blank">configuration</a> by using the <a href="http://docs.spring.io/spring/docs/4.0.6.RELEASE/javadoc-api/index.html?org/springframework/beans/factory/annotation/Autowired.html" title="Annotation Type Autowired" target="_blank">@Autowired</a> annotation for the beans that <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/step/builder/StepBuilder.html" title="Annotation Type EnableBatchProcessing" target="_blank">@EnableBatchProcessing</a> will create. Use the one that you like most. In this case they also imports the data base configuration.</p>
<p></p><pre class="crayon-plain-tag">@Configuration
@EnableBatchProcessing
@Import(DataSourceConfiguration.class)
public class AppConfig {

    @Autowired
    private JobBuilderFactory jobs;

    @Autowired
    private StepBuilderFactory steps;

    // Input, processor, and output definition omitted

    @Bean
    public Job importUserJob() {
        return jobs.get(&quot;importUserJob&quot;).incrementer(new RunIdIncrementer()).flow(step1()).end().build();
    }

    @Bean
    protected Step step1(ItemReader&lt;Person&gt; reader, ItemProcessor&lt;Person, Person&gt; processor, ItemWriter&lt;Person&gt; writer) {
        return steps.get(&quot;step1&quot;)
            .&lt;Person, Person&gt; chunk(10)
            .reader(reader)
            .processor(processor)
            .writer(writer)
            .build();
    }

}</pre><p></p>
<p>We chose another approach: we load it when configuring the application in the main method as you&#8217;ll see shortly. besides, we imported an additional batch configuration (see line 28 at <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/BatchConfiguration.java" title="BatchConfiguration.java" target="_blank">BatchConfiguration.java</a>) to provide an alternate way to launch the application.</p>
<h3>Enable Batch Processing: how it works</h3>
<p>As we said before, we will go a little deeper in how the annotation <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.html" title="EnableBatchProcessing API" target="_blank">@EnableBatchProcessing</a> works.</p>
<p>To remind its goal, this annotation provides a base configuration for building batch jobs by creating a list of beans available to be autowired. An extract of the source code gives us a lot of information:</p>
<p></p><pre class="crayon-plain-tag">@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(BatchConfigurationSelector.class)
public @interface EnableBatchProcessing {

	/**
	 * Indicate whether the configuration is going to be modularized into multiple application contexts. If true then
	 * you should not create any &amp;#64;Bean Job definitions in this context, but rather supply them in separate (child)
	 * contexts through an {@link ApplicationContextFactory}.
	 */
	boolean modular() default false;

}</pre><p></p>
<p>As you can see at line 4, this annotation <a href="http://docs.spring.io/spring/docs/4.0.6.RELEASE/javadoc-api/index.html?org/springframework/context/annotation/Import.html" title="Annotation Type Import" target="_blank">imports</a> an implementation of an <a href="http://docs.spring.io/spring/docs/4.0.6.RELEASE/javadoc-api/index.html?org/springframework/context/annotation/ImportSelector.html" title="Interface ImportSelector" target="_blank">ImportSelector</a>, one of the options to import beans in a configuration class, in particular, to selective import beans according to certain criteria.</p>
<p>This particular implementation, <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/BatchConfigurationSelector.html" title="Class BatchConfigurationSelector" target="_blank">BatchConfigurationSelector</a>, instantiates the expected beans for providing common structure for enabling and using Spring Batch based in the EnableBatchProcessing&#8217;s attribute <strong>modular</strong>.</p>
<p>There are two implementations depending on whether you want the configuration to be modularized into multiple application contexts so that they don’t interfere with each other with the naming and the uniqueness of beans (for instance, beans named <strong>reader</strong>) or not. They are <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/ModularBatchConfiguration.html" title="Class ModularBatchConfiguration" target="_blank">ModularBatchConfiguration</a> and <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/SimpleBatchConfiguration.html" title="Class SimpleBatchConfiguration" target="_blank">SimpleBatchConfiguration</a> respectively. Mainly they both do the same, but the former using an <a href="AutomaticJobRegistrar" title="Class AutomaticJobRegistrar" target="_blank">AutomaticJobRegistrar</a> which is responsible for creating separate <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/context/ApplicationContext.html" title="Interface ApplicationContext" target="_blank">ApplicationContext</a>s for register isolated jobs that are later accesible via the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/JobRegistry.html" title="nterface JobRegistry" target="_blank">JobRegistry</a>, and the latter just creates the main components as lazy proxies that only initialize when a method is called (in order to prevent configuration cycles)</p>
<p>The key concept here is that both extends <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/AbstractBatchConfiguration.html" title="Class AbstractBatchConfiguration" target="_blank">AbstractBatchConfiguration</a> that uses the core interface for this configuration: <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/BatchConfigurer.html" title="Interface BatchConfigurer" target="_blank">BatchConfigurer</a>.</p>
<p>The default implementation, <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/configuration/annotation/DefaultBatchConfigurer.html" title="Class DefaultBatchConfigurer" target="_blank">DefaultBatchConfigurer</a>, provides the beans mentioned above (jobRepository, jobLauncher, jobRegistry, transactionManager, jobBuilders and stepBuilders), for doing so it <u>doesn&#8217;t require a dataSource</u>, it&#8217;s Autowired with required to false, so it will use a Map based JobRepository if its dataSource is null, but you have take care if you have a dataSource eligible for autowiring that doesn&#8217;t contain the expected database schema for the job repository: the batch process will fail in this case.</p>
<p>Spring Boot provides another implementation, <a href="http://docs.spring.io/spring-boot/docs/current/api/index.html?org/springframework/boot/autoconfigure/batch/BasicBatchConfigurer.html" title="Class BasicBatchConfigurer" target="_blank">BasicBatchConfigurer</a>, but this is out of the scope of this entry.</p>
<p>With all this information, we already have a Spring Batch application configured, and we more or less know how this configuration is achieved using Java.</p>
<p>Now it&#8217;s time to run the application. </p>
<h3>Running the sample: JobLauncher</h3>
<p>We have all we need to launch a batch job, the Job to be launched and a JobLauncher, so wait no more and execute this main class: <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/MainJobLauncher.java" title="MainJobLauncher.java" target="_blank">MainJobLauncher</a>.</p>
<p></p><pre class="crayon-plain-tag">@Component
public class MainJobLauncher {

    @Autowired
    JobLauncher jobLauncher;

    @Autowired
    Job importUserJob;

    public static void main(String... args) throws JobParametersInvalidException, JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfiguration.class);

        MainJobLauncher main = context.getBean(MainJobLauncher.class);

        JobExecution jobExecution = main.jobLauncher.run(main.importUserJob, new JobParameters());

        MainHelper.reportResults(jobExecution);
        MainHelper.reportPeople(context.getBean(JdbcTemplate.class));

        context.close();

    }

}</pre><p></p>
<p>First things first. This is the way I like to write main classes. Some people from Spring are used to writing main classes annotated with <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/context/annotation/Configuration.html" title="Annotation Type Configuration" target="_blank">@Configuration</a>, but I&#8217;d rather to annotate them as <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/stereotype/Component.html" title="Annotation Type Component" target="_blank">@Component</a>s in order to separate the actual application and its configuration from the classes that test the functionality.</p>
<p>As Spring component (line 1), it only needs to have the dependencies <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/beans/factory/annotation/Autowired.html" title="Annotation Type Autowired" target="_blank">@Autowired</a>.</p>
<p>That&#8217;s the reason for the <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/ApplicationConfiguration.java" title="ApplicationConfiguration.java" target="_blank">ApplicationConfiguration</a> class. It&#8217;s a <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/context/annotation/Configuration.html" title="Annotation Type Configuration" target="_blank">@Configuration</a> class that also performs a @ComponentScan from its own package, that will find the very <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/MainJobLauncher.java" title="MainJobLauncher.java" target="_blank">MainJobLauncher</a> and the remain <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/context/annotation/Configuration.html" title="Annotation Type Configuration" target="_blank">@Configuration</a> classes, because they are also <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/stereotype/Component.html" title="Annotation Type Component" target="_blank">@Component</a>s: <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/BatchConfiguration.java" title="BatchConfiguration.java" target="_blank">BatchConfiguration</a> and <a href="https://github.com/jbbarquero/spring-batch-sample/blob/master/src/main/java/com/malsolo/springframework/batch/sample/DataSourceConfiguration.java" title="DataSourceConfiguration.java" target="_blank">DataSourceConfiguration</a>.  </p>
<p>As a main class, it creates the Spring Application Context (line 12), it gets the component as a Spring bean (line 14) and then it uses its methods (or attributes in this example. Line 16)</p>
<p>Let&#8217;s back to the Batch application: the line 16 is the call to the JobLauncher that will run the Spring Batch process.</p>
<p>The remaining lines are intended to show the results, both from the job execution and the results in the database.</p>
<p>It will be something like this:</p>
<p></p><pre class="crayon-plain-tag">***********************************************************
importUserJob finished with a status of  (COMPLETED).
* Steps executed:
	step1 : exitCode=COMPLETED;exitDescription=
StepExecution: id=0, version=3, name=step1, status=COMPLETED, exitStatus=COMPLETED, readCount=5, filterCount=0, writeCount=5 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0
***********************************************************

***********************************************************
* People found:

* Found firstName: JILL, lastName: DOE in the database

* Found firstName: JOE, lastName: DOE in the database

* Found firstName: JUSTIN, lastName: DOE in the database

* Found firstName: JANE, lastName: DOE in the database

* Found firstName: JOHN, lastName: DOE in the database
***********************************************************</pre><p></p>
<h3>Running the sample: CommandLineJobRunner</h3>
<p><a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/launch/support/CommandLineJobRunner.html" title="Class CommandLineJobRunner" target="_blank">CommandLineJobRunner</a> is a main class provided by Spring Batch as the primary entry point to <a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#commandLineJobRunner" title="The CommandLineJobRunner" target="_blank">launch a Spring Batch Job</a>.</p>
<p>It requires at least two arguments: <strong>JobConfigurationXmlPath/JobConfigurationClassName</strong> and <strong>jobName</strong>. With the first, it will create an <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/context/ApplicationContext.html" title="Interface ApplicationContext" target="_blank">ApplicationContext</a> by loading a Java Configuration from a class with the same name or by loading an XML Configuration file with the same name.</p>
<p>It has a <a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#domainJobLauncher" title="JobLauncher" target="_blank">JobLauncher</a> attribute that is autowired with the application context via its <a href="http://docs.spring.io/spring/docs/current/javadoc-api/index.html?org/springframework/beans/factory/config/AutowireCapableBeanFactory.html" title="Interface AutowireCapableBeanFactory" target="_blank">AutowireCapableBeanFactory</a> exposed, that is used to autowire the bean properties by type.</p>
<p>It accepts some options (&#8220;-restart&#8221;, &#8220;-next&#8221;, &#8220;-stop&#8221;, &#8220;-abandon&#8221;) as well as parameters for the <a href="http://docs.spring.io/spring-batch/trunk/reference/htmlsingle/#domainJobLauncher" title="JobLauncher" target="_blank">JobLauncher</a> that are converted with the <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/converter/DefaultJobParametersConverter.html" title="Class DefaultJobParametersConverter" target="_blank">DefaultJobParametersConverter</a> as <a href="http://docs.spring.io/spring-batch/apidocs/index.html?org/springframework/batch/core/converter/JobParametersConverter.html" title="Interface JobParametersConverter" target="_blank">JobParametersConverter</a> that expects a &#8216;name=value&#8217; format.</p>
<p>You can declare this main class in the manifest file, directly or using some maven plugin as maven-jar-plugin, maven-shade-plugin or even exec-maven-plugin.</p>
<p>That is, you can invoke from your command line something like this:</p>
<p><strong>$ java CommandLineJobRunner job.xml jobName parameter=value</strong></p>
<p>Well, the sample code is a maven project that you can install (it&#8217;s enough if you package the application) and it allows to manage the dependencies (the mvn dependency:copy-dependencies command copies all the dependencies in the target/dependency directory)</p>
<p>To simplify, I&#8217;ll also copy the generated jar to the same directory of the dependencies in order to invoke the java command more easily:</p>
<p></p><pre class="crayon-plain-tag">~/Documents/git/spring-batch-sample$mvn clean install
[INFO] Scanning for projects...
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
...
~/Documents/git/spring-batch-sample$ mvn dependency:copy-dependencies
[INFO] Scanning for projects...
...
[INFO] Copying spring-batch-core-3.0.1.RELEASE.jar to ~/Documents/git/spring-batch-sample/target/dependency/spring-batch-core-3.0.1.RELEASE.jar
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
...
~/Documents/git/spring-batch-sample$ cp target/spring-batch-sample-0.0.1-SNAPSHOT.jar ./target/dependency/
~/Documents/git/spring-batch-sample$ java -classpath "./target/dependency/*" org.springframework.batch.core.launch.support.CommandLineJobRunner com.malsolo.springframework.batch.sample.ApplicationConfiguration importUserJob
...
12:32:17.039 [main] INFO  o.s.b.c.l.support.SimpleJobLauncher 
- Job: [FlowJob: [name=importUserJob]] 
completed with the following parameters: [{}] 
and the following status: [COMPLETED]
...</pre><p></p>
<p>That&#8217;s all for now.</p>
<p>Since this entry is becoming very large, I&#8217;ll explain other ways to run Spring Batch Jobs in a next post.</p>
]]></content:encoded>
			<wfw:commentRss>http://malsolo.com/blog4java/?feed=rss2&#038;p=260</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
