[[late-binding]] = Late Binding of `Job` and `Step` Attributes Both the XML and flat file examples shown earlier use the Spring `Resource` abstraction to obtain a file. This works because `Resource` has a `getFile` method that returns a `java.io.File`. You can configure both XML and flat file resources by using standard Spring constructs: [tabs] ==== Java:: + The following example shows late binding in Java: + .Java Configuration [source, java] ---- @Bean public FlatFileItemReader flatFileItemReader() { FlatFileItemReader reader = new FlatFileItemReaderBuilder() .name("flatFileItemReader") .resource(new FileSystemResource("file://outputs/file.txt")) ... } ---- XML:: + The following example shows late binding in XML: + .XML Configuration [source, xml] ---- ---- ==== The preceding `Resource` loads the file from the specified file system location. Note that absolute locations have to start with a double slash (`//`). In most Spring applications, this solution is good enough, because the names of these resources are known at compile time. However, in batch scenarios, the file name may need to be determined at runtime as a parameter to the job. This can be solved using `-D` parameters to read a system property. [tabs] ==== Java:: + The following shows how to read a file name from a property in Java: + .Java Configuration [source, java] ---- @Bean public FlatFileItemReader flatFileItemReader(@Value("${input.file.name}") String name) { return new FlatFileItemReaderBuilder() .name("flatFileItemReader") .resource(new FileSystemResource(name)) ... } ---- XML:: + The following example shows how to read a file name from a property in XML: + .XML Configuration [source, xml] ---- ---- ==== All that would be required for this solution to work would be a system argument (such as `-Dinput.file.name="file://outputs/file.txt"`). NOTE: Although you can use a `PropertyPlaceholderConfigurer` here, it is not necessary if the system property is always set because the `ResourceEditor` in Spring already filters and does placeholder replacement on system properties. Often, in a batch setting, it is preferable to parameterize the file name in the `JobParameters` of the job (instead of through system properties) and access them that way. To accomplish this, Spring Batch allows for the late binding of various `Job` and `Step` attributes. [tabs] ==== Java:: + The following example shows how to parameterize a file name in Java: + .Java Configuration [source, java] ---- @StepScope @Bean public FlatFileItemReader flatFileItemReader(@Value("#{jobParameters['input.file.name']}") String name) { return new FlatFileItemReaderBuilder() .name("flatFileItemReader") .resource(new FileSystemResource(name)) ... } ---- XML:: + The following example shows how to parameterize a file name in XML: + .XML Configuration [source, xml] ---- ---- ==== You can access both the `JobExecution` and `StepExecution` level `ExecutionContext` in the same way. [tabs] ==== Java:: + The following example shows how to access the `ExecutionContext` in Java: + .Java Configuration [source, java] ---- @StepScope @Bean public FlatFileItemReader flatFileItemReader(@Value("#{jobExecutionContext['input.file.name']}") String name) { return new FlatFileItemReaderBuilder() .name("flatFileItemReader") .resource(new FileSystemResource(name)) ... } ---- + .Java Configuration [source, java] ---- @StepScope @Bean public FlatFileItemReader flatFileItemReader(@Value("#{stepExecutionContext['input.file.name']}") String name) { return new FlatFileItemReaderBuilder() .name("flatFileItemReader") .resource(new FileSystemResource(name)) ... } ---- XML:: + The following example shows how to access the `ExecutionContext` in XML: + .XML Configuration [source, xml] ---- ---- + .XML Configuration [source, xml] ---- ---- ==== NOTE: Any bean that uses late binding must be declared with `scope="step"`. See xref:step/late-binding.adoc#step-scope[Step Scope] for more information. A `Step` bean should not be step-scoped or job-scoped. If late binding is needed in a step definition, then the components of that step (tasklet, item reade/writer, completion policy, and so on) are the ones that should be scoped instead. NOTE: If you use Spring 3.0 (or above), the expressions in step-scoped beans are in the Spring Expression Language, a powerful general purpose language with many interesting features. To provide backward compatibility, if Spring Batch detects the presence of older versions of Spring, it uses a native expression language that is less powerful and that has slightly different parsing rules. The main difference is that the map keys in the example above do not need to be quoted with Spring 2.5, but the quotes are mandatory in Spring 3.0. // TODO Where is that older language described? It'd be good to have a link to it here. // Also, given that we are up to version 5 of Spring, should we still be talking about // things from before version 3? (In other words, we should provide a link or drop the // whole thing.) [[step-scope]] == Step Scope All of the late binding examples shown earlier have a scope of `step` declared on the bean definition. [tabs] ==== Java:: + The following example shows an example of binding to step scope in Java: + .Java Configuration [source, java] ---- @StepScope @Bean public FlatFileItemReader flatFileItemReader(@Value("#{jobParameters[input.file.name]}") String name) { return new FlatFileItemReaderBuilder() .name("flatFileItemReader") .resource(new FileSystemResource(name)) ... } ---- XML:: + The following example shows an example of binding to step scope in XML: + .XML Configuration [source, xml] ---- ---- ==== Using a scope of `Step` is required to use late binding, because the bean cannot actually be instantiated until the `Step` starts, to let the attributes be found. Because it is not part of the Spring container by default, the scope must be added explicitly, by using the `batch` namespace, by including a bean definition explicitly for the `StepScope`, or by using the `@EnableBatchProcessing` annotation. Use only one of those methods. The following example uses the `batch` namespace: [source, xml] ---- ... ---- The following example includes the bean definition explicitly: [source, xml] ---- ---- [[job-scope]] == Job Scope `Job` scope, introduced in Spring Batch 3.0, is similar to `Step` scope in configuration but is a scope for the `Job` context, so that there is only one instance of such a bean per running job. Additionally, support is provided for late binding of references accessible from the `JobContext` by using `#{..}` placeholders. Using this feature, you can pull bean properties from the job or job execution context and the job parameters. [tabs] ==== Java:: + The following example shows an example of binding to job scope in Java: + .Java Configuration [source, java] ---- @JobScope @Bean public FlatFileItemReader flatFileItemReader(@Value("#{jobParameters[input]}") String name) { return new FlatFileItemReaderBuilder() .name("flatFileItemReader") .resource(new FileSystemResource(name)) ... } ---- + .Java Configuration [source, java] ---- @JobScope @Bean public FlatFileItemReader flatFileItemReader(@Value("#{jobExecutionContext['input.name']}") String name) { return new FlatFileItemReaderBuilder() .name("flatFileItemReader") .resource(new FileSystemResource(name)) ... } ---- XML:: + The following example shows an example of binding to job scope in XML: + .XML Configuration [source, xml] ---- ---- + .XML Configuration [source, xml] ---- ---- ==== Because it is not part of the Spring container by default, the scope must be added explicitly, by using the `batch` namespace, by including a bean definition explicitly for the JobScope, or by using the `@EnableBatchProcessing` annotation (choose only one approach). The following example uses the `batch` namespace: [source, xml] ---- ... ---- The following example includes a bean that explicitly defines the `JobScope`: [source, xml] ---- ---- NOTE: There are some practical limitations of using job-scoped beans in multi-threaded or partitioned steps. Spring Batch does not control the threads spawned in these use cases, so it is not possible to set them up correctly to use such beans. Hence, we do not recommend using job-scoped beans in multi-threaded or partitioned steps. [[scoping-item-streams]] == Scoping `ItemStream` components When using the Java configuration style to define job or step scoped `ItemStream` beans, the return type of the bean definition method should be at least `ItemStream`. This is required so that Spring Batch correctly creates a proxy that implements this interface, and therefore honors its contract by calling `open`, `update` and `close` methods as expected. It is recommended to make the bean definition method of such beans return the most specific known implementation, as shown in the following example: .Define a step-scoped bean with the most specific return type [source, java] ---- @Bean @StepScope public FlatFileItemReader flatFileItemReader(@Value("#{jobParameters['input.file.name']}") String name) { return new FlatFileItemReaderBuilder() .resource(new FileSystemResource(name)) // set other properties of the item reader .build(); } ----