diff --git a/docs/src/site/docbook/reference/appendix.xml b/docs/src/site/docbook/reference/appendix.xml index d6d5fc997..48cb76dbe 100644 --- a/docs/src/site/docbook/reference/appendix.xml +++ b/docs/src/site/docbook/reference/appendix.xml @@ -10,15 +10,13 @@ Available Item Readers - + Item Reader - Type of Item Provided - Description @@ -28,8 +26,6 @@ AbstractItemCountingItemStreamItemReader - java.lang.Object - Abstract base class that provides basic restart capabilities by counting the number of items returned from an ItemReader. @@ -38,8 +34,6 @@ ListItemReader - java.lang.Object - Provides the items from a list, one at a time @@ -47,8 +41,6 @@ ItemReaderAdapter - java.lang.Object - Adapts any class to the ItemReader interface. @@ -56,8 +48,6 @@ AggregateItemReader - java.util.Collection - An ItemReader that delivers a list as its item, storing up objects from the injected ItemReader until they are ready to be packed out as a collection. This ItemReader should @@ -71,9 +61,7 @@ FlatFileItemReader - java.lang.String - - Reads from a flat file, includes ItemStream + Reads from a flat file. Includes ItemStream and Skippable functionality. See section on Read from a File @@ -81,8 +69,6 @@ StaxEventItemReader - java.lang.Object - Reads via StAX. See HOWTO - Read from a File @@ -90,45 +76,28 @@ JdbcCursorItemReader - java.lang.Object - Reads from a database cursor via JDBC. See HOWTO - Read from a Database - - DrivingQueryItemReader - - java.lang.Object - - Base class for operations that read from a - database based on a single driving query. Configured by injecting - a KeyGenerator object. See HOWTO - Read from a Database - - HibernateCursorItemReader - java.lang.Object - Reads from a cursor based on an HQL query. See section on Reading from a Database - IbatisDrivingQueryItemReader + IbatisPagingItemReader - java.lang.Object - - Reads via iBATIS based on a driving query. See - HOWTO - Read from a Database + Reads via iBATIS based on a query. Pages + through the rows so that large datasets can be read without + running out of memory. See HOWTO - Read from a Database JmsItemReader - javax.jms.Message - Given a Spring JmsOperations object and a JMS Destination or destination name to send errors, provides items received through the injected JmsOperations receive() @@ -138,8 +107,6 @@ JpaPagingItemReader - java.lang.Object - Given a JPQL statement, pages through the rows, such that large datasets can be read without running out of memory @@ -148,8 +115,6 @@ JdbcPagingItemReader - java.lang.Object - Given a SQL statement, pages through the rows, such that large datasets can be read without running out of memory @@ -165,15 +130,13 @@
Available Item Writers - + Item Writer - Type of Item Written - Description @@ -182,29 +145,14 @@ AbstractItemStreamItemWriter - java.lang.Object - Abstract base class that combines the ItemStream and ItemWriter interfaces. - - BatchSqlUpdateItemWriter - - java.lang.Object - - ItemWriter that uses - batching freatures from a PreparedStatement - if available and can take rudimentary steps to locate a failure - during a flush. - - CompositeItemWriter - java.lang.Object - Passes an item to the process method of each in an injected List of ItemWriter objects @@ -213,8 +161,6 @@ ItemWriterAdapter - java.lang.Object - Adapts any class to the ItemWriter interface. @@ -222,8 +168,6 @@ PropertyExtractingDelegatingItemWriter - java.lang.Object - Extends AbstractMethodInvokingDelegator creating arguments on the fly. Arguments are created by retrieving the values from the fields in the item to be processed (via a @@ -234,19 +178,12 @@ FlatFileItemWriter - java.lang.Object - - Attempts to convert the item to a String, Collection or array using an injected - Coverter and then - recurses. + Writes to a flat file. Includes ItemStream and + Skippable functionality. See section on Writing to a File - HibernateAwareItemWriter - - java.lang.Object + HibernateItemWriter This item writer is hibernate session aware and handles some transaction-related work that a non-"hibernate @@ -255,9 +192,16 @@ - JpaAwareItemWriter + JdbcBatchItemWriter - java.lang.Object + Uses batching freatures from a + PreparedStatement, if available, and can + take rudimentary steps to locate a failure during a + flush. + + + + JpaItemWriter This item writer is JPA EntityManager aware and handles some transaction-related work that a non-"jpa aware" @@ -266,9 +210,7 @@ - StaxEventWriterItemWriter - - java.lang.Object + StaxEventItemWriter Uses an ObjectToXmlSerializer implementation to diff --git a/docs/src/site/docbook/reference/common-patterns.xml b/docs/src/site/docbook/reference/common-patterns.xml index c8e7d0ffd..36fd7304f 100644 --- a/docs/src/site/docbook/reference/common-patterns.xml +++ b/docs/src/site/docbook/reference/common-patterns.xml @@ -5,29 +5,31 @@ Common Batch Patterns Some batch jobs can be assembled purely from off-the-shelf components - in Spring Batch, mostly the ItemReader and - ItemWriter implementations. Where this is not - possible (the majority of cases) the main API entry points for application + in Spring Batch. For instance the ItemReader and + ItemWriter implementations can be configured to cover + a wide range of scenarios. However, for the majority of cases, custom code + will have to be written. The main API entry points for application developers are the Tasklet, ItemReader, ItemWriter and the various listener interfaces. Most simple batch jobs will be able to use off-the-shelf input from a Spring Batch ItemReader, - but it is very often the case that there are custom concerns in the - processing and writing, which normally leads developers to implement an - ItemWriter, or - ItemTransformer. + but it is often the case that there are custom concerns in the processing + and writing, which require developers to implement an + ItemWriter or + ItemProcessor. - Here we provide a few examples of common patterns in custom business - logic, mainly using the listener interfaces . It should be noted that an - ItemReader or ItemWriter can - implement the listener interfaces as well if appropriate. + Here, we provide a few examples of common patterns in custom business + logic. These examples primarily feature the listener interfaces. It should + be noted that an ItemReader or + ItemWriter can implement a listener interface as + well, if appropriate.
Logging Item Processing and Failures A common use case is the need for special handling of errors in a step, item by item, perhaps logging to a special channel, or inserting a - record into a database. The StepHandlerStep + record into a database. A chunk-oriented Step (created from the step factory beans) allows users to implement this use case with a simple ItemReadListener, for errors on read, and an ItemWriteListener, for errors on @@ -71,14 +73,16 @@
Stopping a Job Manually for Business Reasons - Spring Batch provides a stop() method through the JobLauncher - interface, but this is really aimed at the operator, rather than the - application programmer. Sometimes it is more convenient or makes more - sense to stop a job execution from within the business logic. + Spring Batch provides a stop() method + through the JobLauncher interface, but this is + really for use by the operator rather than the application programmer. + Sometimes it is more convenient or makes more sense to stop a job + execution from within the business logic. - The simplest thing to do is to throw a RuntimeException (one that - isn't retried indefinitely or skipped), For example, a custom exception - type could be used, as in the example below: + The simplest thing to do is to throw a + RuntimeException (one that isn't retried + indefinitely or skipped). For example, a custom exception type could be + used, as in the example below: public class PoisonPillItemWriter implements ItemWriter<T> { @@ -95,15 +99,15 @@ Another simple way to stop a step from executing is to simply return null from the ItemReader: - public class EarlyCompletionItemReader extends AbstractItemReader { + public class EarlyCompletionItemReader implements ItemReader<T> { - private ItemReader delegate; + private ItemReader<T> delegate; - public void setDelegate(ItemReader delegate) { ... } + public void setDelegate(ItemReader<T> delegate) { ... } - public Object read() throws Exception { + public T read() throws Exception { - Object item = delegate.read(); + T item = delegate.read(); if (isEndItem(item)) { return null; // end the step here @@ -138,9 +142,10 @@ StepExecution, which is checked by the Step implementations in the framework in between item processing. To implement this alternative, we need access to the - current StepExecution, and this can be achieved by implementing a - StepListener and registering it with the Step. Here is an example of a - listener that sets the flag: + current StepExecution, and this can be achieved by + implementing a StepListener and registering it with + the Step. Here is an example of a listener that + sets the flag: public class CustomItemWriter extends ItemListenerSupport implements StepListener { @@ -160,7 +165,7 @@ } - The default behaviour here when the flag is set is for the step to + The default behavior here when the flag is set is for the step to throw a JobInterruptedException. This can be controlled through the StepInterruptionPolicy, but the only choice is to throw or not throw an exception, so this is always @@ -172,7 +177,7 @@ A very common requirement is to aggregate information during the output process and to append a record at the end of a file summarizing the - data, or providing a checksum. This can also be achieved with a callbacks + data, or providing a checksum. This can also be achieved with a callback in the step, normally as part of a custom ItemWriter. In this case, since a job is accumulating state that should not be lost if the job aborts, the @@ -206,10 +211,8 @@ } public void write(Trade item) { - delegate.write(item); totalAmount += item.getAmount(); - } } @@ -220,8 +223,9 @@ ExecutionContext. In this way we can be sure that when the open() callback is received on a restart. The framework garuntees we always get the last value that was committed. It - should be noted that it is not always necessary to implement ItemStream. - For example, if the ItemWriter is re-runnable, in the sense that it + should be noted that it is not always necessary to implement + ItemStream. For example, if the + ItemWriter is re-runnable, in the sense that it maintains its own state in a transactional resource like a database, there is no need to maintain state within the writer itself.
@@ -272,11 +276,9 @@ - As you can see, an existing DAO can be used to obtain a full 'Foo' - object using the key obtained from the driving query. In Spring Batch, - driving query style input is implemented with a - DrivingQueryItemReader, which has only one - dependency: a KeyCollector + An ItemProcessor should be used to transform the key obtained from + the driving query into a full 'Foo' object. An existing DAO can be used to + query for the full object based on the key.
diff --git a/docs/src/site/docbook/reference/domain.xml b/docs/src/site/docbook/reference/domain.xml index 81fff2400..2a625148e 100644 --- a/docs/src/site/docbook/reference/domain.xml +++ b/docs/src/site/docbook/reference/domain.xml @@ -389,7 +389,7 @@ will be kicked off again for 01-01, starting where it left off and completing successfully at 9:30. Because it's now the next day, the 01-02 job must be run as well, which is kicked off just afterwards at - 9:31, and completes in it's normal one hour time at 10:30. There is no + 9:31, and completes in its normal one hour time at 10:30. There is no requirement that one JobInstance be kicked off after another, unless there is potential for the two jobs to attempt to access the same data, causing issues with locking at the database level. @@ -573,7 +573,7 @@ JobExecution. However, if a step fails to execute because the step before it fails, there will be no execution persisted for it. A StepExecution will only be created when - it's Step is actually started. + its Step is actually started. Step executions are represented by objects of the StepExecution class. Each execution contains a diff --git a/docs/src/site/docbook/reference/glossary.xml b/docs/src/site/docbook/reference/glossary.xml index bc2246eb2..a269a7e1b 100644 --- a/docs/src/site/docbook/reference/glossary.xml +++ b/docs/src/site/docbook/reference/glossary.xml @@ -99,8 +99,8 @@ An item represents the smallest ammount of complete data for - processing. In the most simple terms this might mean a line in a file, - a row in a database table, or a particular element in an XML + processing. In the simplest terms, this might mean a line in a file, a + row in a database table, or a particular element in an XML file. @@ -119,7 +119,7 @@ Commit Interval - A set of LUWs constitute a commit interval. + A set of LUWs processed within a single transaction. @@ -147,7 +147,7 @@ Restartable - - a job that can be executed again and will assume the same + A job that can be executed again and will assume the same identity as when run initially. In othewords, it is has the same job instance id. @@ -157,14 +157,14 @@ Rerunnable - a job that is restartable and manages it's own state in terms of + A job that is restartable and manages its own state in terms of previous run's record processing. An example of a rerunnable step is one based on a driving query. If the driving query can be formed so that it will limit the processed rows when the job is restarted than it is re-runnable. This is managed by the application logic. Often times a condition is added to the where statement to limit the rows returned by the driving query with something like "and processedFlag - != true". + != true". @@ -189,9 +189,8 @@ calling a block of code, retry is stateful, and continually calls the same block of code with the same input, until it either succeeds, or some type of retry limit has been exceeded. It is only generally - useful if the operation is non-deterministic meaning that a retry on a - subsequent invocation might succeed because something in the - environment has improved. + useful if a subsequent invocation of the operation might succeed + because something in the environment has improved. @@ -214,4 +213,4 @@ - \ No newline at end of file + diff --git a/docs/src/site/docbook/reference/job.xml b/docs/src/site/docbook/reference/job.xml index 223154879..4c265f61d 100644 --- a/docs/src/site/docbook/reference/job.xml +++ b/docs/src/site/docbook/reference/job.xml @@ -20,20 +20,21 @@ - While the Job object may seem like a simple container for steps, there - are many configuration options that developers should be aware of. - Furthermore, there are many considerations for how a - Job will be run and how its meta data will be stored - during that run. This chapter will explain the various configuration options - and runtime concerns of a Job. + While the Job object may seem like a simple + container for steps, there are many configuration options of which a + developers must be aware . Furthermore, there are many considerations for + how a Job will be run and how its meta-data will be + stored during that run. This chapter will explain the various configuration + options and runtime concerns of a Job.
Configuring a Job There are multiple implementations of the Job interface, however, the namespace abstracts away - the differences in configuration. It has only three required dependencies: - a name, JobRepository, and a list of Steps. + linkend="job">Job interface, however, the + namespace abstracts away the differences in configuration. It has only + three required dependencies: a name, JobRepository, + and a list of Steps. <job id="footballJob"> @@ -57,20 +58,26 @@ + Note that if the job repository's default id is overridden, it must + be explicitly specified on every + Step as well as on + the Job. +
Restartability - One key concern when execution a batch job, is what happens when a - failed job is restarted? A Job is considered to have been 'restarted' if - the same JobInstance has more than one - JobExecution. Ideally, all jobs should be able to start up where they - left off, but there are scenarios where this is not possible. It is entirely up to the developer to ensure that a new - instance is always created in this scenario. However, Spring - Batch does provide some help. If a Job should never be restarted, but - should always be run as part of a new - JobInstance, then the restartable property may be - set to 'false': + One key issue when execution a batch job concerns the behavior of + a Job when it is restarted? The launching of a + Job is considered to be a 'restart' if a + JobExecution already exists for the particular + JobInstance. Ideally, all jobs should be able to + start up where they left off, but there are scenarios where this is not + possible. It is entirely up to the developer to + ensure that a new JobInstance is created in this scenario. + However, Spring Batch does provide some help. If a + Job should never be restarted, but should always + be run as part of a new JobInstance, then the + restartable property may be set to 'false': <job id="footballJob" restartable="false"> @@ -131,8 +138,9 @@ - Listeners can be added to a SimpleJob via - the setJobListeners property: + JobListeners can be added to a + SimpleJob via the listeners element on the + job: <job id="footballJob"> @@ -146,17 +154,17 @@ - It should be noted that afterJob will be called regardless of the - success or failure of the Job. If success or - failure needs to be determined it can be obtained from the - JobExecution: + It should be noted that afterJob will be + called regardless of the success or failure of the + Job. If success or failure needs to be determined + it can be obtained from the JobExecution: void afterJob(JobExecution jobExecution){ - if( jobExecution.getStatus = BatchStatus.COMPLETED ){ + if( jobExecution.getStatus() == BatchStatus.COMPLETED ){ //job success } - else if(jobExecution.getStatus = BatchStatus.FAILED){ + else if(jobExecution.getStatus() == BatchStatus.FAILED){ //job failure } } @@ -168,14 +176,14 @@ JobFactory and Stateful Components in Steps Unlike many traditional Spring applications, many of the - components of a batch application are stateful, the file readers and + components of a batch application are stateful; the file readers and writers are obvious examples. The recommended way to deal with this is to create a fresh ApplicationContext for each job execution. If the Job is launched from the - command line with CommandLineJobRunner this is - trivial. For more complex launching scenarios, where jobs are executed - in parallel or serially from the same process, some extra steps have to - be taken to ensure that the ApplicationContext is + command line with CommandLineJobRunner, this is + trivial. For more complex launching scenarios where jobs are executed in + parallel or serially from the same process, some extra steps have to be + taken to ensure that the ApplicationContext is refreshed. This is preferable to using prototype scope for the stateful beans because then they would not receive lifecycle callbacks from the container at the end of use. (e.g. through destroy-method in XML) @@ -196,12 +204,13 @@ Configuring a JobRepository As described in earlier, the JobRepository is used for basic CRUD - operations of the various persisted domain objects within Spring Batch, - such as JobExecution and StepExecution. It is required by many of the - major framework features, such as the JobLauncher, + linkend="jobRepository">JobRepository is + used for basic CRUD operations of the various persisted domain objects + within Spring Batch, such as JobExecution and + StepExecution. It is required by many of the major + framework features, such as the JobLauncher, Job, and Step. The batch - namespace abstract much of the implementation details of the + namespace abstracts away many of the implementation details of the JobRepository implementations and their collaborators. However, there are still a few configuration options available: @@ -226,7 +235,7 @@ If the namespace is used, transactional advice will be automatically created around the repository. This is to ensure that the batch meta data, including state that is necessary for restarts after a - failure, is persisted correctly. The behaviour of the framework is not + failure, is persisted correctly. The behavior of the framework is not well defined if the repository methods are not transactional. The isolation level in the create* method attributes is specified separately to ensure that when jobs are launched, if two @@ -246,7 +255,7 @@ If the namespace or factory beans aren't used then it is also - essential to configure the transactional behaviour of the repository + essential to configure the transactional behavior of the repository using AOP: @@ -266,7 +275,7 @@ This fragment can be used as is, with almost no changes. Remember also to include the appropriate namespace declarations and to make sure - spring-tx and spring-aop (or the whole of spring) is on the + spring-tx and spring-aop (or the whole of spring) are on the classpath.
@@ -294,7 +303,7 @@ as SYSTEM.TEST_JOB_EXECUTION. - Only the table prefix is configurable, the table and column + Only the table prefix is configurable. The table and column names are not.
@@ -303,10 +312,11 @@ In-Memory Repository There are scenarios in which you may not want to persist your - domain objects to the database. One reason may be speed, storing domain + domain objects to the database. One reason may be speed; storing domain objects at each commit point takes extra time. Another reason may be - that you just don't need to persist status for a particular job. Spring - batch provides a solution: + that you just don't need to persist status for a particular job. For + this reason, Spring batch provides an in-memory Map version of the job + respository: <bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean" /> @@ -318,7 +328,7 @@ The most basic implementation of the JobLauncher interface is the - SimpleJobLauncher. It's only required dependency is + SimpleJobLauncher. Its only required dependency is a JobRepository, in order to obtain an execution: @@ -327,10 +337,11 @@ <property name="jobRepository" ref="jobRepository" /> </bean> - Once a JobExecution is obtained, - it is passed to the execute method of Job, - ultimately returning the JobExecution to the - caller: + Once a JobExecution is + obtained, it is passed to the execute method of + Job, ultimately returning the + JobExecution to the caller: @@ -346,13 +357,13 @@ - The sequence is straightforward, and works well when launched from a - scheduler, but causes issues when trying to launch from an HTTP request. - In this scenario, the launching needs to be done asynchronously, so that - the SimpleJobLauncher returns immediately to it's - caller. This is because it is not good practice to keep an HTTP request - open for the amount of time needed by long running processes such as - batch. An example sequence is below: + The sequence is straightforward and works well when launched from a + scheduler. However, issues arise when trying to launch from an HTTP + request. In this scenario, the launching needs to be done asynchronously + so that the SimpleJobLauncher returns immediately + to its caller. This is because it is not good practice to keep an HTTP + request open for the amount of time needed by long running processes such + as batch. An example sequence is below: @@ -388,16 +399,16 @@
Running a Job - At a minimum, launching a batch job requires two things: the Job to - be launched and a JobLauncher. Both can be - contained within the same context or different contexts. For example, if - launching a job from the command line, a new JVM will be instantiated for - each Job, and thus every job will have it's own - JobLauncher. However, if running from within a web - container within the scope of an HttpRequest, there - will usually be one JobLauncher, configured for - asynchronous job launching, that multiple requests will invoke to launch - their jobs. + At a minimum, launching a batch job requires two things: the + Job to be launched and a + JobLauncher. Both can be contained within the same + context or different contexts. For example, if launching a job from the + command line, a new JVM will be instantiated for each Job, and thus every + job will have its own JobLauncher. However, if + running from within a web container within the scope of an + HttpRequest, there will usually be one + JobLauncher, configured for asynchronous job + launching, that multiple requests will invoke to launch their jobs.
Running Jobs from the Command Line @@ -421,29 +432,32 @@ CommandLineJobRunner. It's important to note that this is just one way to bootstrap your application, but there are many ways to launch a Java process, and this class should in no way be - viewed as definitive. It performs four tasks: + viewed as definitive. The CommandLineJobRunner + performs four tasks: - Loads the appropriate Application Context + Load the appropriate + ApplicationContext - Parses command line arguments into JobParameters + Parse command line arguments into + JobParameters - Locates the appropriate job based on arguments + Locate the appropriate job based on arguments - Uses the JobLauncher provided in the application context to - launch the job. + Use the JobLauncher provided in the + application context to launch the job. - All of these tasks are accomplished based completely upon the - arguments passed in. The following are required arguments: + All of these tasks are accomplished using only the arguments + passed in. The following are required arguments:
CommandLineJobRunner arguments @@ -479,22 +493,21 @@ This example is using the same 'EndOfDay' example from . The first argument is 'endOfDayJob.xml', which is the Spring ApplicationContext containing the - Job. The second argument, 'endOfDay' represents the job name. The - final argument, 'schedule.date=01-01-2008' will be converted into - JobParameters. An example of the XML - configuration is below: + Job. The second argument, 'endOfDay' represents + the job name. The final argument, 'schedule.date=01-01-2008' will be + converted into JobParameters. An example of the + XML configuration is below: - <bean id="endOfDay" - class="org.springframework.batch.core.job.SimpleJob"> - <property name="steps"> - <bean id="step1" parent="simpleStep" /> + <job id="endOfDay"> + <steps> + <step name="step1" parent="simpleStep" /> <!-- Step details removed for clarity --> - </property> - </bean> + </steps> + </job> <!-- Launcher details removed for clarity --> - <bean id="jobLauncher" - class="org.springframework.batch.core.launch.support.SimpleJobLauncher" /> + <beans: bean id="jobLauncher" + class="org.springframework.batch.core.launch.support.SimpleJobLauncher" /> This example is overly simplistic, since there are many more requirements to a run a batch job in Spring Batch in general, but it @@ -507,22 +520,23 @@
ExitCodes - When launching a batch job from the command-line, it is often - from an enterprise scheduler. Most schedulers are fairly dumb, and - work only at the process level. Meaning, they only know about some + When launching a batch job from the command-line, an enterprise + scheduler is often used. Most schedulers are fairly dumb and work only + at the process level. This means that they only know about some operating system process such as a shell script that they're invoking. In this scenario, the only way to communicate back to the scheduler about the success or failure of a job is through return codes. A - number is returned to a scheduler that is told how to interpret the - result. In the simple case: 0 is success and 1 is failure. However, - there may be scenarios such as: If job A returns 4 kick off job B, if - it returns 5 kick off job C. This type of behavior is configured at - the scheduler level, but it is important that a processing framework - such as Spring Batch provide a way to return a numeric representation - of of the 'Exit Code' for a particular batch job. In Spring Batch this - is encapsulated within an ExitStatus, which is - covered in more detail in Chapter 5. For the purposes of discussing - exit codes, the only important thing to know is that an + return code is a number that is returned to a scheduler by the process + that indicates the result of the run. In the simplest case: 0 is + success and 1 is failure. However, there may be more complex + scenarios: If job A returns 4 kick off job B, and if it returns 5 kick + off job C. This type of behavior is configured at the scheduler level, + but it is important that a processing framework such as Spring Batch + provide a way to return a numeric representation of the 'Exit Code' + for a particular batch job. In Spring Batch this is encapsulated + within an ExitStatus, which is covered in more + detail in Chapter 5. For the purposes of discussing exit codes, the + only important thing to know is that an ExitStatus has an exit code property that is set by the framework (or the developer) and is returned as part of the JobExecution returned from the @@ -554,7 +568,7 @@ it will be injected into the runner after the context is created. All that needs to be done to provide your own ExitCodeMapper is to declare the implementation - as a root level bean, and ensure it's part of the + as a root level bean and ensure that it is part of the ApplicationContext that is loaded by the runner.
@@ -589,12 +603,12 @@ A JobLauncher uses the JobRepository to create new - JobExecution objects, and run them. + JobExecution objects and run them. Job and Step implementations later use the same JobRepository for basic updates of the same executions during the running of a Job. - The basic operations suffice for simple scenarios. However, in a large - batch environment with hundreds of batch jobs and complex scheduling + The basic operations suffice for simple scenarios, but in a large batch + environment with hundreds of batch jobs and complex scheduling requirements, more advanced access of the meta data is required: @@ -654,9 +668,10 @@ Earlier in this chapter, it was mentioned that the table prefix of the - JobRepository can be modified to allow for different versions or - schemas. Because the JobExplorer is working with the same tables, it too - needs the ability to set a prefix: + JobRepository can be modified to allow for + different versions or schemas. Because the + JobExplorer is working with the same tables, it + too needs the ability to set a prefix:
<bean id="jobExplorer" class="org.springframework.batch.core.explore.support.JobExplorerFactoryBean" @@ -741,35 +756,43 @@ self-explanatory, and more detailed explanations can be found on the javadoc - of the interface. However, the 'startNextInstance' method is - worth noting. This method will always start a new instance of a Job. + of the interface. However, the + startNextInstance method is worth noting. This + method will always start a new instance of a Job. This can be extremely useful if there are serious issues in a - JobExecution, and the Job + JobExecution and the Job needs to be started over again from the beginning. Unlike JobLauncher though, which requires a new - JobParameters that will trigger a new JobInstance - if they are different than any previous one, the startNextInstance - method will use the JobParametersIncrementer tied to the Job to force - the Job to a new instance: + JobParameters object that will trigger a new + JobInstance if the parameters are different from + any previous set of parameters, the + startNextInstance method will use the + JobParametersIncrementer tied to the + Job to force the Job to a + new instance: public interface JobParametersIncrementer { JobParameters getNext(JobParameters parameters); + } The contract of JobParametersIncrementer is - that, given a JobParameters, it - will return the 'next' parameter by incrementing any values it may - contain. This strategy is useful because the framework has no way of - knowing what changes to the JobParameters make it the 'next' instance. - For example, if the only value in JobParameters is a date, and the next - instance should be created, should that value be incremented by one day? - Or one week? (if the job is weekly for instance) The same can be said - for any numerical values that help to identify the Job, as shown - below: + that, given a JobParameters + object, it will return the 'next' JobParameters + object by incrementing any necessary values it may contain. This + strategy is useful because the framework has no way of knowing what + changes to the JobParameters make it the 'next' + instance. For example, if the only value in + JobParameters is a date, and the next instance + should be created, should that value be incremented by one day? Or one + week (if the job is weekly for instance)? The same can be said for any + numerical values that help to identify the Job, + as shown below: public class SampleIncrementer implements JobParametersIncrementer { @@ -786,12 +809,13 @@ In this example, the value with a key of 'run.id' is used to - discriminate between JobInstances. If the JobParameters passed in is - null, it can be assumed that the Job has never been run before and thus - it's initial state can be returned. However, if not, the old value is - obtained, incremented by one, and returned. An incrementer can be - associated with Job via the 'incrementer' attribute in the - namespace: + discriminate between JobInstances. If the + JobParameters passed in is null, it can be + assumed that the Job has never been run before + and thus its initial state can be returned. However, if not, the old + value is obtained, incremented by one, and returned. An incrementer can + be associated with Job via the 'incrementer' + attribute in the namespace: <job id="footballJob" incrementer="sampleIncrementer"> @@ -819,8 +843,8 @@ The shutdown is not immediate, since there is no way to force immediate shutdown, especially if the execution is currently in developer code that the framework has no control over, such as a - business service. What it does mean, is that as soon as control is - returned back to the framework, it will set the status of the current + business service. However, as soon as control is returned back to the + framework, it will set the status of the current StepExecution to BatchStatus.STOPPED, save it, then do the same for the JobExecution before finishing. diff --git a/docs/src/site/docbook/reference/readersAndWriters.xml b/docs/src/site/docbook/reference/readersAndWriters.xml index 471990e57..f77b298e5 100644 --- a/docs/src/site/docbook/reference/readersAndWriters.xml +++ b/docs/src/site/docbook/reference/readersAndWriters.xml @@ -477,7 +477,7 @@ processing locations and vice versa. File moving utilities are beyond the scope of the spring batch architecture but it is not unusual for batch job streams to include file moving utilities as steps in the job - stream. Its sufficient that the batch architecture only needs to know + stream. It is sufficient that the batch architecture only needs to know how to locate the files to be processed. Spring Batch begins the process of feeding the data into the pipe from this starting point. However, FlatFileItemReader<Player> itemReader = new FlatFileItemReader<Player>(); itemReader.setResource(new FileSystemResource("resources/players.csv")); - //DelimitedLineTokenizer defaults to comma as it's delimiter + //DelimitedLineTokenizer defaults to comma as its delimiter LineMapper<Player> lineMapper = new DefaultLineMapper<Player>(); lineMapper.setLineTokenizer(new DelimitedLineTokenizer()); lineMapper.setFieldSetMapper(new PlayerFieldSetMapper()); @@ -973,7 +973,7 @@ All of the file reading examples up to this point have all made a key assumption for simplicity's sake: all of the records in a file - have the same format. However, this may not always be the case. Its + have the same format. However, this may not always be the case. It is very common that a file might have records with different formats that need to be tokenized differently and mapped to different objects. The following excerpt from a file illustrates this: @@ -1219,7 +1219,7 @@ Simplified File Writing Example Now that the LineAggregator interface and - it's most basic implementation, + its most basic implementation, PassThroughLineAggregator, have been defined, the basic flow of writing can be explained: @@ -2408,9 +2408,9 @@ existing service needs to act as an ItemReader or ItemWriter, either to satisfy the dependency of another Spring Batch class, or because it truly is the main - ItemReader for a step. Its fairly trivial to write - an adaptor class for each service that needs wrapping, but because its - such a common concern, Spring Batch provides implementations: + ItemReader for a step. It is fairly trivial to + write an adaptor class for each service that needs wrapping, but because + it is such a common concern, Spring Batch provides implementations: ItemReaderAdapter and ItemWriterAdapter. Both classes implement the standard Spring method invoking the delegate pattern and are fairly simple diff --git a/docs/src/site/docbook/reference/schema-appendix.xml b/docs/src/site/docbook/reference/schema-appendix.xml index 465edd343..9dbe2a36c 100644 --- a/docs/src/site/docbook/reference/schema-appendix.xml +++ b/docs/src/site/docbook/reference/schema-appendix.xml @@ -16,7 +16,7 @@ respectively. ExecutionContext maps to both BATCH_JOB_EXECUTION_CONTEXT and BATCH_STEP_EXECUTION_CONTEXT. The JobRepository is responsible for saving and storing - each Java object into it's correct table. The following appendix describes + each Java object into its correct table. The following appendix describes the meta-data tables in detail, along with many of the design decisions that were made when creating them. When viewing the various table creation statements below, it is important to realize that the data types used are @@ -49,7 +49,7 @@ to try and save the value, if the version number has change it will throw OptimisticLockingFailureException, indicating there has been an error with concurrent access. This check is - necessary, since even though different batch jobs may be running in + necessary since, even though different batch jobs may be running in different machines, they are all using the same database tables. @@ -57,11 +57,11 @@ Identity BATCH_JOB_INSTANCE, BATCH_JOB_EXECUTION, and BATCH_STEP_EXECUTION - each contain columns ending in _ID, which act as primary keys for their - respective tables. However, they are not database generated keys, but - rather are generated by separate sequences. This is necessary because - after inserting one of the domain objects into the database, the key it - is given needs to be set on the actual object, so that they can be + each contain columns ending in _ID. These fields act as primary keys for + their respective tables. However, they are not database generated keys, + but rather they are generated by separate sequences. This is necessary + because after inserting one of the domain objects into the database, the + key it is given needs to be set on the actual object so that they can be uniquely identified in Java. Newer database drivers (Jdbc 3.0 and up) support this feature with database generated keys, but rather than requiring it, sequences were used. Each variation of the schema will @@ -431,8 +431,8 @@ INSERT INTO BATCH_JOB_SEQ values(0); The BATCH_JOB_EXECUTION_CONTEXT table holds all information relevant to an Job's ExecutionContext. There is exactly one - ExecutionContext per - StepExecution, and it contains all of the job-level + Job ExecutionContext per + JobExecution, and it contains all of the job-level data that is needed for a particular job execution. This data typically represents the state that must be retrieved after a failure so that a JobInstance can 'start from where it left